Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
104 commits
Select commit Hold shift + click to select a range
676ef95
test: add tests for options.fs in fs streams
julianduque May 1, 2020
c5a38fe
doc: fix style and grammer in buffer.md
seishun May 1, 2020
cc02c73
http: fixes memory retention issue with FreeList and HTTPParser
leidegre May 1, 2020
07372e9
doc: explicitly doc package.exports is breaking
MylesBorins Apr 26, 2020
a292630
src: retrieve binding data from the context
joyeecheung Apr 19, 2020
a56b600
Revert "src: add aliased-buffer-overflow abort test"
richardlau May 1, 2020
5ff3192
Revert "src: add test/abort build tasks"
richardlau May 1, 2020
cf47698
src: use BaseObjectPtr in StreamReq::Dispose
jasnell Apr 27, 2020
25443fa
doc: doc and test URLSearchParams discrepancy
jasnell May 4, 2020
cf88ed8
doc: update napi_async_init documentation
mhdawson Apr 30, 2020
b2fb01a
stream: make from read one at a time
ronag May 1, 2020
4ae6130
n-api: add uint32 test for -1
May 5, 2020
0572943
doc: add warnings about transferring Buffers and ArrayBuffer
jasnell May 5, 2020
dab5c38
doc: remove AsyncWrap mentions from async_hooks.md
puzpuzpuz May 5, 2020
6ffec50
doc: add troubleshooting guide for AsyncLocalStorage
puzpuzpuz May 5, 2020
4465d23
wasi: prevent syscalls before start
tniessen May 4, 2020
2c49dd3
doc: specify unit of time passed to `fs.utimes`
SimenB May 4, 2020
c6a8cd0
doc: fix md issue in src/README.md
juanarbol May 3, 2020
5b42d81
doc: add Uint8Array to `end` and `write`
rexagod May 2, 2020
27b814c
module: lazy load 'getOptionValue' in initializeLoader
himself65 May 2, 2020
e20fe53
doc: update Buffer(size) documentation
seishun May 1, 2020
b5dcfbf
doc: removed unnecessary util imports from vm examples
WalasPrime Apr 30, 2020
84974d3
doc: mention python3-distutils dependency in BUILDING.md
osher Apr 30, 2020
6bca487
lib: fix grammar in internal/bootstrap/loaders.js
szTheory May 2, 2020
302408e
test: skip some console tests on dumb terminal
AdamMajer Apr 30, 2020
6f54c2b
test: rename test-lookupService-promises
rickyes Apr 27, 2020
a9e4fdb
doc: correct description of `decipher.setAuthTag` in crypto.md
jbuhacoff Apr 27, 2020
ed41494
src: clean up large pages code
May 5, 2020
6a26eee
wasi: fix poll_oneoff memory interface
cjihrig May 5, 2020
0cbee57
doc: add warning for socket.connect reuse
ronag May 5, 2020
ad86807
module: better error for named exports from cjs
MylesBorins May 5, 2020
548cedd
src: split out callback queue implementation from Environment
addaleax May 6, 2020
94d0a08
lib: refactored scheduling policy assignment
yashLadha Apr 5, 2020
0a78925
meta: add issue template for API reference docs
DerekNonGeneric Apr 20, 2020
ef25033
src: fix invalid windowBits=8 gzip segfault
bnoordhuis Apr 24, 2020
736ca65
zlib: reject windowBits=8 when mode=GZIP
bnoordhuis Apr 24, 2020
b634d4b
http: set IncomingMessage.destroyed
ronag Apr 28, 2020
41c5524
http2: add `bytesWritten` test for `Http2Stream`
rexagod Apr 21, 2020
eedc131
tls: reset secureConnecting on client socket
davedoesdev May 2, 2020
cae2051
buffer: improve copy() performance
seishun May 2, 2020
ba66b21
deps: upgrade npm to 6.14.5
ruyadorno May 4, 2020
398bdf4
perf_hooks: fix error message for invalid entryTypes
targos May 7, 2020
1d2c81f
test: add hr-time Web platform tests
targos May 7, 2020
804982c
tools: add eslint rule to only pass through 'test' to debuglog
BridgeAR Mar 9, 2020
cf03fe5
tools: remove obsolete no-restricted-syntax eslint rules
BridgeAR Mar 9, 2020
3de9dd9
src: remove unnecessary Isolate::GetCurrent() calls
addaleax May 8, 2020
a133a88
lib: fix typo in timers insert function comment
danbev May 8, 2020
e1e57a4
tools: update ESLint to 7.0.0
cjihrig May 8, 2020
cc5c8e0
http: don't destroy completed request
ronag Apr 28, 2020
b061655
async_hooks: move PromiseHook handler to JS
Qard Apr 16, 2020
f33e866
http: expose http.validate-header-name/value
osher Apr 28, 2020
1dcf66c
fs: add .ref() and .unref() methods to watcher classes
rickyes Apr 28, 2020
fd9c7c2
src: fix compiler warning in async_wrap.cc
addaleax May 9, 2020
0d77eec
src: add support for TLA
devsnek Nov 12, 2019
5b2cd44
test: fix test-net-throttle
Trott May 9, 2020
f3129b2
src: fix typo in comment in async_wrap.cc
danbev May 11, 2020
4f0cd64
doc: fix typo in n-api.md
danbev May 9, 2020
b41affb
doc: add note about clientError writable handling
ShogunPanda May 8, 2020
066ca98
src: use MaybeLocal.ToLocal instead of IsEmpty
danbev May 8, 2020
c9c16c0
src: delete unused variables to resolve compile time print warning
rickyes May 11, 2020
1999607
src: remove unused using declarations in node.cc
danbev May 6, 2020
d292633
src: add primordials to arguments comment
danbev May 9, 2020
331f0b3
deps: update to ICU 67.1
targos May 9, 2020
85cffb8
test: update WPT interfaces and hr-time
joyeecheung May 12, 2020
f31b262
test: refactor WPTRunner
joyeecheung May 6, 2020
7d4db35
build: fix `--error-on-warn` for macOS
richardlau May 11, 2020
34e7400
build: enable `--error-on-warn` for POSIX workflows
richardlau May 11, 2020
fd89ef1
src: refactor Reallocate since it introduced in upstream v8
gengjiawen Apr 10, 2020
6d2aaaf
tls: fix --tls-keylog option
mildsunrise May 12, 2020
354ff4f
src: small modification to NgHeader
jasnell May 7, 2020
0ffa040
doc: add examples for implementing ESM
rosaxxny Apr 30, 2020
0257386
src: remove deprecated FinalizationRegistry hooks
devsnek May 12, 2020
1a9771a
repl: improve repl preview
BridgeAR May 4, 2020
d33dcf1
repl: show reference errors during preview
BridgeAR May 4, 2020
69061dc
repl: replace hard coded core module list with actual list
BridgeAR May 7, 2020
95842db
test: refactor test/parallel/test-bootstrap-modules.js
BridgeAR May 7, 2020
6257cf2
repl: improve repl autocompletion for require calls
BridgeAR May 7, 2020
c2d2dfc
module: do not check circular dependencies for exported proxies
BridgeAR May 10, 2020
c2cf978
Revert "vm: add importModuleDynamically option to compileFunction"
mcollina May 12, 2020
d3e2fc8
test: fix test-dns-idna2008
Trott May 12, 2020
182aaf5
doc: enhance guides by fixing and making grammar more consistent
ChrisAHolland Apr 29, 2020
12391c7
fs: clean up Dir.read() uv_fs_t data before calling into JS
addaleax May 6, 2020
c7c420e
fs: forbid concurrent operations on Dir handle
addaleax May 7, 2020
2dc5db8
cli: add `--trace-atomics-wait` flag
addaleax Dec 5, 2019
b1a7fda
worker: call CancelTerminateExecution() before exiting Locker
addaleax May 10, 2020
dd4789b
async_hooks: clear async_id_stack for terminations in more places
addaleax May 11, 2020
b93a723
test: regression tests for async_hooks + Promise + Worker interaction
addaleax May 10, 2020
8ada953
src: replace to CHECK_NOT_NULL in node_crypto
himself65 May 13, 2020
8f91338
doc: fix stream example
addaleax May 15, 2020
35aae31
module: add specific error for dir import
aduh95 May 3, 2020
e53de96
esm: improve commonjs hint on module not found
aduh95 May 14, 2020
9119344
tools: enable no-else-return lint rule
lpinca Apr 8, 2020
db7bb94
repl: deprecate repl.inputStream and repl.outputStream
BridgeAR May 7, 2020
ed83202
repl: remove obsolete completer variable
BridgeAR May 7, 2020
7aa581f
repl: deprecate repl._builtinLibs
BridgeAR May 7, 2020
5e5aa0b
src: add #include <string> in json_utils.h
zcbenz May 10, 2020
9d1e577
worker: fix crash when .unref() is called during exit
addaleax May 14, 2020
099f18e
src: distinguish refed/unrefed threadsafe Immediates
addaleax May 9, 2020
24faa37
buffer,n-api: release external buffers from BackingStore callback
addaleax May 9, 2020
7f9ccd6
doc: fix extension in esm example
devsnek May 14, 2020
cc27949
doc: prepare 14.x changelog for remark update
Trott May 15, 2020
453affe
tools: update dependencies for markdown linting
Trott May 15, 2020
e4ad464
src: add default: case to silence compiler warning
addaleax May 18, 2020
5d81e4d
2020-05-19, Version 14.3.0 (Current)
codebytere May 18, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
cli: add --trace-atomics-wait flag
Adds a flag that helps with debugging deadlocks due to incorrectly
implemented `Atomics.wait()` calls.

PR-URL: #33292
Reviewed-By: Gus Caplan <me@gus.host>
Reviewed-By: David Carlier <devnexen@gmail.com>
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Joyee Cheung <joyeec9h3@gmail.com>
  • Loading branch information
addaleax authored and codebytere committed May 16, 2020
commit 2dc5db8c07d0b9dcaa54bbb83b3339b1933da6c9
15 changes: 15 additions & 0 deletions benchmark/worker/atomics-wait.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
'use strict';
/* global SharedArrayBuffer */

const common = require('../common.js');
const bench = common.createBenchmark(main, {
n: [1e7]
});

function main({ n }) {
const i32arr = new Int32Array(new SharedArrayBuffer(4));
bench.start();
for (let i = 0; i < n; i++)
Atomics.wait(i32arr, 0, 1); // Will return immediately.
bench.end(n);
}
30 changes: 30 additions & 0 deletions doc/api/cli.md
Original file line number Diff line number Diff line change
Expand Up @@ -814,6 +814,33 @@ added: v12.0.0
Set default [`tls.DEFAULT_MIN_VERSION`][] to 'TLSv1.3'. Use to disable support
for TLSv1.2, which is not as secure as TLSv1.3.

### `--trace-atomics-wait`
<!-- YAML
added: REPLACEME
-->

Print short summaries of calls to [`Atomics.wait()`][] to stderr.
The output could look like this:

```text
(node:15701) [Thread 0] Atomics.wait(<address> + 0, 1, inf) started
(node:15701) [Thread 0] Atomics.wait(<address> + 0, 1, inf) did not wait because the values mismatched
(node:15701) [Thread 0] Atomics.wait(<address> + 0, 0, 10) started
(node:15701) [Thread 0] Atomics.wait(<address> + 0, 0, 10) timed out
(node:15701) [Thread 0] Atomics.wait(<address> + 4, 0, inf) started
(node:15701) [Thread 1] Atomics.wait(<address> + 4, -1, inf) started
(node:15701) [Thread 0] Atomics.wait(<address> + 4, 0, inf) was woken up by another thread
(node:15701) [Thread 1] Atomics.wait(<address> + 4, -1, inf) was woken up by another thread
```

The fields here correspond to:

* The thread id as given by [`worker_threads.threadId`][]
* The base address of the `SharedArrayBuffer` in question, as well as the
byte offset corresponding to the index passed to `Atomics.wait()`
* The expected value that was passed to `Atomics.wait()`
* The timeout passed to `Atomics.wait`

### `--trace-deprecation`
<!-- YAML
added: v0.8.0
Expand Down Expand Up @@ -1203,6 +1230,7 @@ Node.js options that are allowed are:
* `--tls-min-v1.1`
* `--tls-min-v1.2`
* `--tls-min-v1.3`
* `--trace-atomics-wait`
* `--trace-deprecation`
* `--trace-event-categories`
* `--trace-event-file-pattern`
Expand Down Expand Up @@ -1472,12 +1500,14 @@ $ node --max-old-space-size=1536 index.js
```

[`--openssl-config`]: #cli_openssl_config_file
[`Atomics.wait()`]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Atomics/wait
[`Buffer`]: buffer.html#buffer_class_buffer
[`SlowBuffer`]: buffer.html#buffer_class_slowbuffer
[`process.setUncaughtExceptionCaptureCallback()`]: process.html#process_process_setuncaughtexceptioncapturecallback_fn
[`tls.DEFAULT_MAX_VERSION`]: tls.html#tls_tls_default_max_version
[`tls.DEFAULT_MIN_VERSION`]: tls.html#tls_tls_default_min_version
[`unhandledRejection`]: process.html#process_event_unhandledrejection
[`worker_threads.threadId`]: worker_threads.html##worker_threads_worker_threadid
[Chrome DevTools Protocol]: https://chromedevtools.github.io/devtools-protocol/
[REPL]: repl.html
[ScriptCoverage]: https://chromedevtools.github.io/devtools-protocol/tot/Profiler#type-ScriptCoverage
Expand Down
4 changes: 4 additions & 0 deletions doc/node.1
Original file line number Diff line number Diff line change
Expand Up @@ -363,6 +363,10 @@ but the option is supported for compatibility with older Node.js versions.
Set default minVersion to 'TLSv1.3'. Use to disable support for TLSv1.2 in
favour of TLSv1.3, which is more secure.
.
.It Fl -trace-atomics-wait
Print short summaries of calls to
.Sy Atomics.wait() .
.
.It Fl -trace-deprecation
Print stack traces for deprecations.
.
Expand Down
45 changes: 45 additions & 0 deletions src/node.cc
Original file line number Diff line number Diff line change
Expand Up @@ -227,11 +227,56 @@ int Environment::InitializeInspector(
}
#endif // HAVE_INSPECTOR && NODE_USE_V8_PLATFORM

#define ATOMIC_WAIT_EVENTS(V) \
V(kStartWait, "started") \
V(kWokenUp, "was woken up by another thread") \
V(kTimedOut, "timed out") \
V(kTerminatedExecution, "was stopped by terminated execution") \
V(kAPIStopped, "was stopped through the embedder API") \
V(kNotEqual, "did not wait because the values mismatched") \

static void AtomicsWaitCallback(Isolate::AtomicsWaitEvent event,
Local<v8::SharedArrayBuffer> array_buffer,
size_t offset_in_bytes, int64_t value,
double timeout_in_ms,
Isolate::AtomicsWaitWakeHandle* stop_handle,
void* data) {
Environment* env = static_cast<Environment*>(data);

const char* message;
switch (event) {
#define V(key, msg) \
case Isolate::AtomicsWaitEvent::key: \
message = msg; \
break;
ATOMIC_WAIT_EVENTS(V)
#undef V
}

fprintf(stderr,
"(node:%d) [Thread %" PRIu64 "] Atomics.wait(%p + %zx, %" PRId64
", %.f) %s\n",
static_cast<int>(uv_os_getpid()),
env->thread_id(),
array_buffer->GetBackingStore()->Data(),
offset_in_bytes,
value,
timeout_in_ms,
message);
}

void Environment::InitializeDiagnostics() {
isolate_->GetHeapProfiler()->AddBuildEmbedderGraphCallback(
Environment::BuildEmbedderGraph, this);
if (options_->trace_uncaught)
isolate_->SetCaptureStackTraceForUncaughtExceptions(true);
if (options_->trace_atomics_wait) {
isolate_->SetAtomicsWaitCallback(AtomicsWaitCallback, this);
AddCleanupHook([](void* data) {
Environment* env = static_cast<Environment*>(data);
env->isolate()->SetAtomicsWaitCallback(nullptr, nullptr);
}, this);
}

#if defined HAVE_DTRACE || defined HAVE_ETW
InitDTrace(this);
Expand Down
4 changes: 4 additions & 0 deletions src/node_options.cc
Original file line number Diff line number Diff line change
Expand Up @@ -435,6 +435,10 @@ EnvironmentOptionsParser::EnvironmentOptionsParser() {
"throw an exception on deprecations",
&EnvironmentOptions::throw_deprecation,
kAllowedInEnvironment);
AddOption("--trace-atomics-wait",
"trace Atomics.wait() operations",
&EnvironmentOptions::trace_atomics_wait,
kAllowedInEnvironment);
AddOption("--trace-deprecation",
"show stack traces on deprecations",
&EnvironmentOptions::trace_deprecation,
Expand Down
1 change: 1 addition & 0 deletions src/node_options.h
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,7 @@ class EnvironmentOptions : public Options {
std::string redirect_warnings;
bool test_udp_no_try_send = false;
bool throw_deprecation = false;
bool trace_atomics_wait = false;
bool trace_deprecation = false;
bool trace_exit = false;
bool trace_sync_io = false;
Expand Down
79 changes: 79 additions & 0 deletions test/parallel/test-trace-atomics-wait.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
'use strict';
require('../common');
const assert = require('assert');
const child_process = require('child_process');
const { Worker } = require('worker_threads');

if (process.argv[2] === 'child') {
const i32arr = new Int32Array(new SharedArrayBuffer(8));
assert.strictEqual(Atomics.wait(i32arr, 0, 1), 'not-equal');
assert.strictEqual(Atomics.wait(i32arr, 0, 0, 10), 'timed-out');

new Worker(`
const i32arr = require('worker_threads').workerData;
Atomics.store(i32arr, 1, -1);
Atomics.notify(i32arr, 1);
Atomics.wait(i32arr, 1, -1);
`, { eval: true, workerData: i32arr });

Atomics.wait(i32arr, 1, 0);
assert.strictEqual(Atomics.load(i32arr, 1), -1);
Atomics.store(i32arr, 1, 0);
Atomics.notify(i32arr, 1);
return;
}

const proc = child_process.spawnSync(
process.execPath,
[ '--trace-atomics-wait', __filename, 'child' ],
{ encoding: 'utf8', stdio: [ 'inherit', 'inherit', 'pipe' ] });

if (proc.status !== 0) console.log(proc);
assert.strictEqual(proc.status, 0);

const SABAddress = proc.stderr.match(/Atomics\.wait\((?<SAB>.+) \+/).groups.SAB;
const actualTimeline = proc.stderr
.replace(new RegExp(SABAddress, 'g'), '<address>')
.replace(new RegExp(`\\(node:${proc.pid}\\) `, 'g'), '')
.replace(/\binf(inity)?\b/gi, 'inf')
.replace(/\r/g, '')
.trim();
console.log('+++ normalized stdout +++');
console.log(actualTimeline);
console.log('--- normalized stdout ---');

const begin =
`[Thread 0] Atomics.wait(<address> + 0, 1, inf) started
[Thread 0] Atomics.wait(<address> + 0, 1, inf) did not wait because the \
values mismatched
[Thread 0] Atomics.wait(<address> + 0, 0, 10) started
[Thread 0] Atomics.wait(<address> + 0, 0, 10) timed out`;

const expectedTimelines = [
`${begin}
[Thread 0] Atomics.wait(<address> + 4, 0, inf) started
[Thread 1] Atomics.wait(<address> + 4, -1, inf) started
[Thread 0] Atomics.wait(<address> + 4, 0, inf) was woken up by another thread
[Thread 1] Atomics.wait(<address> + 4, -1, inf) was woken up by another thread`,
`${begin}
[Thread 0] Atomics.wait(<address> + 4, 0, inf) started
[Thread 0] Atomics.wait(<address> + 4, 0, inf) was woken up by another thread
[Thread 1] Atomics.wait(<address> + 4, -1, inf) started
[Thread 1] Atomics.wait(<address> + 4, -1, inf) did not wait because the \
values mismatched`,
`${begin}
[Thread 0] Atomics.wait(<address> + 4, 0, inf) started
[Thread 1] Atomics.wait(<address> + 4, -1, inf) started
[Thread 0] Atomics.wait(<address> + 4, 0, inf) was woken up by another thread
[Thread 1] Atomics.wait(<address> + 4, -1, inf) did not wait because the \
values mismatched`,
`${begin}
[Thread 0] Atomics.wait(<address> + 4, 0, inf) started
[Thread 0] Atomics.wait(<address> + 4, 0, inf) did not wait because the \
values mismatched
[Thread 1] Atomics.wait(<address> + 4, -1, inf) started
[Thread 1] Atomics.wait(<address> + 4, -1, inf) did not wait because the \
values mismatched`
];

assert(expectedTimelines.includes(actualTimeline));