about summary refs log tree commit diff stats
path: root/src
diff options
context:
space:
mode:
authorbptato <nincsnevem662@gmail.com>2024-12-05 21:06:59 +0100
committerbptato <nincsnevem662@gmail.com>2024-12-05 21:07:18 +0100
commitb92f653d6f4f9b3b862777e5c150c035f14cbd30 (patch)
treee3d1a8c5509a690c1b257cddd4734eedd7ceedea /src
parentc056cbfb5e4708d605e4f9547412fdb049258d4a (diff)
downloadchawan-b92f653d6f4f9b3b862777e5c150c035f14cbd30.tar.gz
loader: fix heisenbug
Unconditionally registering output handles on resume could result in a
failed assertion on double-register.

The bug would appear like:
resume (register) -> handleRead -> pushBuffer -> currentBuffer is nil ->
register again

handleWrite had a very high likelihood of occurring between resume and
handleRead, and that hid the bug by immediately unregistering the handle
after resume. In fact, I haven't been able to reproduce the bug at all
today, and only found it after poring over the source...

Fix this by not registering output handles that are empty (except
if the istream is already finished, in which case it will just be
unregistered).
Diffstat (limited to 'src')
-rw-r--r--src/server/loader.nim7
1 files changed, 6 insertions, 1 deletions
diff --git a/src/server/loader.nim b/src/server/loader.nim
index b0e96ee3..833ff139 100644
--- a/src/server/loader.nim
+++ b/src/server/loader.nim
@@ -121,6 +121,8 @@ proc newInputHandle(ostream: PosixStream; outputId, pid: int;
     ownerPid: pid,
     suspended: suspended
   ))
+  when defined(debug):
+    handle.outputs[^1].url = handle.url
   return handle
 
 func cap(buffer: LoaderBuffer): int {.inline.} =
@@ -411,6 +413,8 @@ proc redirectToFile(ctx: LoaderContext; output: OutputHandle;
       istreamAtEnd: output.istreamAtEnd,
       outputId: ctx.getOutputId()
     ))
+    when defined(debug):
+      output.parent.outputs[^1].url = output.parent.url
   return true
 
 proc addCacheFile(ctx: LoaderContext; client: ClientData; output: OutputHandle):
@@ -1281,7 +1285,8 @@ proc resume(ctx: LoaderContext; stream: SocketStream; client: ClientData;
     let output = ctx.findOutput(id, client)
     if output != nil:
       output.suspended = false
-      ctx.register(output)
+      if not output.isEmpty or output.istreamAtEnd:
+        ctx.register(output)
   stream.sclose()
 
 proc equalsConstantTime(a, b: ClientKey): bool =
98835'>580bdb48 ^
a8ad394e ^


44979ac7 ^
d88878d3 ^
a8ad394e ^
b768c8b5 ^

a8ad394e ^
ab1441a2 ^
dfeb5889 ^
c0664300 ^
a8ad394e ^

1093737c ^
4257ecb1 ^

44cba501 ^
1ed9580c ^
a7524bc3 ^
02117328 ^
1ed9580c ^
37558fba ^

1ed9580c ^
37558fba ^
1ed9580c ^
90c6ba46 ^
1ed9580c ^

eeb0f71c ^
1ed9580c ^


841f9073 ^
2612b72d ^
be40e206 ^
2612b72d ^
1ed9580c ^
214eac6e ^

2612b72d ^
4257ecb1 ^
0269129d ^



9b797f3c ^
0269129d ^
6f1119d2 ^
f1875919 ^
89c7de77 ^
55b3e9d4 ^

89c7de77 ^
a3dccce2 ^
06882c01 ^

0269129d ^
a7de5933 ^


0bf9d324 ^
a7de5933 ^
0bf9d324 ^




a7de5933 ^
0bf9d324 ^





cd084c7e ^
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100