Commit f66e514
authored
fix(wall): don't derive PersistentContextPtr from node::ObjectWrap (#385)
* fix(wall): don't derive PersistentContextPtr from node::ObjectWrap
node::ObjectWrap registers a per-instance environment cleanup hook in
its constructor and calls RemoveEnvironmentCleanupHook from its
destructor. That teardown path CHECKs the Environment is still alive:
node[650]: void node::RemoveEnvironmentCleanupHook(
v8::Isolate*, CleanupHook, void*) at ../src/api/hooks.cc:142
Assertion failed: (env) != nullptr
3: node::RemoveEnvironmentCleanupHook(...)
4: node::ObjectWrap::RemoveCleanupHook()
5: node::ObjectWrap::~ObjectWrap()
6: dd::PersistentContextPtr::~PersistentContextPtr()
8: node::ObjectWrap::WeakCallback(...)
A PCP is owned by a weak V8 handle, so V8 decides when it dies — and V8
runs weak callbacks during isolate teardown, after the Environment is
gone. The CHECK then aborts the process with SIGABRT.
The wrapper only ever needed two things from the base class: the
internal-field pointer that GetContextPtrSignalSafe reads, and a weak
handle to hang the object's lifetime on. Neither needs a cleanup hook —
~WallProfiler already walks the live list and deletes any PCP V8 has not
collected, which is what keeps LSAN quiet at exit. So hold the weak
Persistent directly and drop the base class.
~PersistentContextPtr resets the handle, which cancels the weak callback
when ~WallProfiler is the one doing the deleting and is a no-op when we
arrived from the callback itself.
Reproduced on main under ASAN (which perturbs GC timing enough to make
it deterministic) as an abort during teardown after the Time Profiler
tests; the full ASAN suite goes from exit 134 to 158 passing with no
leaks reported.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
* fix(wall): tag the internal-field store for Node 26
Node 26 requires an EmbedderDataTypeTag on
Object::SetAlignedPointerInInternalField:
error: no matching function for call to
'v8::Object::SetAlignedPointerInInternalField(int, dd::PersistentContextPtr*)'
note: candidate: 'void v8::Object::SetAlignedPointerInInternalField(
int, void*, v8::EmbedderDataTypeTag)'
note: candidate expects 3 arguments, 2 provided
node::ObjectWrap::Wrap hid this: its header handles the tag internally,
so taking over the store exposed the version difference. Add the setter
counterpart to the existing GetAlignedPointerFromInternalField helper and
use it, so both ends of the internal-field access agree on
kEmbedderDataTypeTagDefault.
Verified on Node 20, 24 and 26 (the last is where AsyncContextFrame is on
by default, so it actually exercises the PCP path): builds clean, 158
passing, ASAN exit 0 with no leaks or aborts.1 parent aac1e50 commit f66e514
1 file changed
Lines changed: 58 additions & 15 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
106 | 106 | | |
107 | 107 | | |
108 | 108 | | |
109 | | - | |
| 109 | + | |
| 110 | + | |
| 111 | + | |
| 112 | + | |
| 113 | + | |
| 114 | + | |
| 115 | + | |
| 116 | + | |
| 117 | + | |
| 118 | + | |
| 119 | + | |
| 120 | + | |
| 121 | + | |
| 122 | + | |
| 123 | + | |
| 124 | + | |
| 125 | + | |
| 126 | + | |
| 127 | + | |
| 128 | + | |
| 129 | + | |
| 130 | + | |
| 131 | + | |
| 132 | + | |
| 133 | + | |
| 134 | + | |
| 135 | + | |
| 136 | + | |
| 137 | + | |
| 138 | + | |
| 139 | + | |
| 140 | + | |
| 141 | + | |
| 142 | + | |
| 143 | + | |
110 | 144 | | |
111 | 145 | | |
112 | 146 | | |
| |||
125 | 159 | | |
126 | 160 | | |
127 | 161 | | |
| 162 | + | |
| 163 | + | |
| 164 | + | |
| 165 | + | |
128 | 166 | | |
129 | 167 | | |
| 168 | + | |
| 169 | + | |
| 170 | + | |
| 171 | + | |
| 172 | + | |
130 | 173 | | |
131 | 174 | | |
132 | 175 | | |
| |||
139 | 182 | | |
140 | 183 | | |
141 | 184 | | |
142 | | - | |
| 185 | + | |
| 186 | + | |
143 | 187 | | |
144 | 188 | | |
145 | 189 | | |
146 | 190 | | |
147 | 191 | | |
148 | 192 | | |
149 | | - | |
| 193 | + | |
| 194 | + | |
| 195 | + | |
| 196 | + | |
150 | 197 | | |
151 | 198 | | |
152 | 199 | | |
| |||
167 | 214 | | |
168 | 215 | | |
169 | 216 | | |
170 | | - | |
171 | | - | |
172 | | - | |
173 | | - | |
174 | | - | |
175 | | - | |
176 | | - | |
177 | | - | |
178 | | - | |
| 217 | + | |
| 218 | + | |
| 219 | + | |
| 220 | + | |
| 221 | + | |
179 | 222 | | |
180 | 223 | | |
181 | 224 | | |
| |||
678 | 721 | | |
679 | 722 | | |
680 | 723 | | |
681 | | - | |
682 | | - | |
683 | | - | |
| 724 | + | |
| 725 | + | |
| 726 | + | |
684 | 727 | | |
685 | 728 | | |
686 | 729 | | |
| |||
0 commit comments