Drain background writers before process exit
Serialize writer submission and shutdown, enqueue explicit stop messages after accepted records, and finish the final file batch before joining. Keep drained process-wide channel storage until exit to avoid the Nim 2.2.10 Channel.close mutex teardown defect. Cover empty records, multiple destinations, joined producers, and concurrent shutdown. Include writer lifecycle sanitizer tests in nimble test and update usage documentation. Validation: all 32 unit tests, eight writer exit scenarios, and writer lifecycle ThreadSanitizer tests pass. The full suite retains the known configuration refresh, timestamp, and default allocator failures.
This commit is contained in:
1 parent
b2d0e9dade
commit
d5e3b9c301
7 files changed
+241
-125
No files matched your search
+24
-7
@@ -134,7 +134,8 @@ suite "ORC ownership and configuration regressions":
|
||||
check destroyed == 1
|
||||
|
||||
suite "Background writer shutdown regressions":
|
||||
for destination in ["file", "console"]:
|
||||
for destination in ["file", "console", "stderr", "file-empty", "console-empty",
|
||||
"files", "file-parallel", "console-parallel"]:
|
||||
test destination & " writer drains accepted messages at normal process exit":
|
||||
let directory = createTempDir("namespaced_logging_shutdown_", "")
|
||||
let outputPath = directory / "messages.log"
|
||||
@@ -150,9 +151,25 @@ suite "Background writer shutdown regressions":
|
||||
check exitCode == 0
|
||||
require fileExists(outputPath)
|
||||
|
||||
let received = readFile(outputPath).splitLines()
|
||||
# Check every record and its order, not just file existence. splitLines
|
||||
# includes one final empty item because each record ends with a newline.
|
||||
check received.len == 10_001
|
||||
for i in 0 ..< min(10_000, received.len - 1):
|
||||
check received[i] == "message " & $i
|
||||
if destination.endsWith("-parallel"):
|
||||
let received = readFile(outputPath).splitLines()
|
||||
require received.len == 10_001
|
||||
var next = [0, 2_500, 5_000, 7_500]
|
||||
for line in received[0 ..< 10_000]:
|
||||
require line.startsWith("message ")
|
||||
let number = parseInt(line[8 .. ^1])
|
||||
require number in 0 ..< 10_000
|
||||
let worker = number div 2_500
|
||||
check number == next[worker]
|
||||
inc next[worker]
|
||||
check next == [2_500, 5_000, 7_500, 10_000]
|
||||
else:
|
||||
var expected: string
|
||||
for i in 0 ..< 10_000:
|
||||
if destination == "file-empty" and i mod 128 == 0:
|
||||
expected.add("\n")
|
||||
expected.add("message " & $i & "\n")
|
||||
check readFile(outputPath) == expected
|
||||
if destination == "files":
|
||||
require fileExists(outputPath & ".second")
|
||||
check readFile(outputPath & ".second") == expected
|
||||
Reference in new issue
Block a user