Commit 10cd8c8
committed
fix(otel-thread-ctx): detect AsyncContextFrame by reading CPED natively
#397 replaced the execArgv inference with a feature detection, but the probe
was indirect: it overrode `enterWith` on a throwaway AsyncLocalStorage and
checked whether `run()` dispatched through it. That `run()` goes through the
instance property is unspecified, and anything patching AsyncLocalStorage can
break it — including dd-trace-js, which patches async-context machinery. The
resulting false negative is the failure #397 set out to fix: `enter()` throwing
inside a diagnostic-channel subscriber, in application code.
Ask the question directly instead. `cpedMapContains(key, value)` reports
whether the isolate's ContinuationPreservedEmbedderData binds a key to a value,
so calling it from inside a `run()` with the probe storage and its own store
observes the property the addon actually depends on. It is the same slot, and
the same "is it a Map" question, that WallProfiler::SetContext asks before
storing a context; the key is the one whose identity hash is published as
otel_thread_ctx_nodejs_v1.als_identity_hash for the out-of-process reader to
look up. Verified empirically that the frame is keyed by the storage instance
with the store as value.
Checking the key and value rather than just "CPED holds a Map" matters: CPED is
a general embedder slot, so a Map another addon left there must not answer for
us — that would resurrect the silent false positive, where the writer looks
healthy from JS while readers see records nothing updates.
Uses the public v8::Map::Get, not the raw OrderedHashMap walk in map-get.hh.
Conflating "is ACF on" with "is our layout knowledge correct" would report a V8
layout change as ACF being unavailable; layout has its own coverage.
Lives in binding.cc rather than wall.cc so it works on Windows: wall.cc's
`#ifndef _WIN32` block is there for SIGPROF and the v8::base::TimeTicks symbol
trick, neither of which a CPED read needs. Gated on NODE_MAJOR_VERSION >= 22,
returning false below, which is the correct answer there rather than a missing
export. Total by construction — no context, slot unset or not a Map, key absent,
or a malformed call all yield false, never a throw, because the writer calls
this from ensureHook().
Detection routes verified on both Node lines: 24 default-on, 24 off via command
line, 24 off via NODE_OPTIONS, 22 off by default, 22 on via command line, 22 on
via NODE_OPTIONS. Five new tests pin the key/value discrimination; mutating the
helper to a bare IsMap check fails three of them and none of the pre-existing
ones. 124 passing on macOS, 175 passing / 2 pending in test:docker.1 parent 9ac10de commit 10cd8c8
3 files changed
Lines changed: 178 additions & 9 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
29 | 29 | | |
30 | 30 | | |
31 | 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 | + | |
32 | 95 | | |
33 | 96 | | |
34 | 97 | | |
| |||
56 | 119 | | |
57 | 120 | | |
58 | 121 | | |
| 122 | + | |
59 | 123 | | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
15 | 15 | | |
16 | 16 | | |
17 | 17 | | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
18 | 35 | | |
19 | 36 | | |
20 | 37 | | |
| |||
39 | 56 | | |
40 | 57 | | |
41 | 58 | | |
42 | | - | |
43 | | - | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
44 | 75 | | |
45 | 76 | | |
46 | 77 | | |
47 | | - | |
48 | | - | |
49 | | - | |
50 | | - | |
51 | | - | |
52 | | - | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
| 81 | + | |
| 82 | + | |
| 83 | + | |
| 84 | + | |
53 | 85 | | |
54 | | - | |
| 86 | + | |
55 | 87 | | |
56 | 88 | | |
57 | 89 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
15 | 15 | | |
16 | 16 | | |
17 | 17 | | |
| 18 | + | |
18 | 19 | | |
19 | 20 | | |
20 | 21 | | |
21 | 22 | | |
22 | 23 | | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
23 | 28 | | |
24 | 29 | | |
25 | 30 | | |
| |||
119 | 124 | | |
120 | 125 | | |
121 | 126 | | |
| 127 | + | |
| 128 | + | |
| 129 | + | |
| 130 | + | |
| 131 | + | |
| 132 | + | |
| 133 | + | |
| 134 | + | |
| 135 | + | |
| 136 | + | |
| 137 | + | |
| 138 | + | |
| 139 | + | |
| 140 | + | |
| 141 | + | |
| 142 | + | |
| 143 | + | |
| 144 | + | |
| 145 | + | |
| 146 | + | |
| 147 | + | |
| 148 | + | |
| 149 | + | |
| 150 | + | |
| 151 | + | |
| 152 | + | |
| 153 | + | |
| 154 | + | |
| 155 | + | |
| 156 | + | |
| 157 | + | |
| 158 | + | |
| 159 | + | |
| 160 | + | |
| 161 | + | |
| 162 | + | |
| 163 | + | |
| 164 | + | |
| 165 | + | |
| 166 | + | |
| 167 | + | |
| 168 | + | |
| 169 | + | |
| 170 | + | |
| 171 | + | |
| 172 | + | |
| 173 | + | |
| 174 | + | |
| 175 | + | |
| 176 | + | |
| 177 | + | |
| 178 | + | |
| 179 | + | |
| 180 | + | |
| 181 | + | |
| 182 | + | |
| 183 | + | |
| 184 | + | |
| 185 | + | |
| 186 | + | |
| 187 | + | |
| 188 | + | |
| 189 | + | |
| 190 | + | |
| 191 | + | |
| 192 | + | |
| 193 | + | |
| 194 | + | |
0 commit comments