Skip to content

Commit d1f4936

Browse files
addaleaxTrott
authored andcommitted
src: improve checked uv loop close output
Addon developers may run into this when not closing libuv handles inside Workers. Previously, output may have included unhelpful statements such as `uv loop at ... has 0 active handles`, which may sound like everything’s supposed to be fine actually. So, instead of printing the active handle count, print the total handle count and mark active handles individually. Also, fix the test for this to work properly and make sure that parsing finishes properly. PR-URL: #30814 Reviewed-By: Richard Lau <riclau@uk.ibm.com> Reviewed-By: Rich Trott <rtrott@gmail.com> Reviewed-By: David Carlier <devnexen@gmail.com> Reviewed-By: Colin Ihrig <cjihrig@gmail.com> Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl>
1 parent a2cfb7d commit d1f4936

File tree

2 files changed

+24
-14
lines changed

2 files changed

+24
-14
lines changed

src/debug_utils.cc

+9-4
Original file line numberDiff line numberDiff line change
@@ -292,19 +292,21 @@ void PrintLibuvHandleInformation(uv_loop_t* loop, FILE* stream) {
292292
struct Info {
293293
std::unique_ptr<NativeSymbolDebuggingContext> ctx;
294294
FILE* stream;
295+
size_t num_handles;
295296
};
296297

297-
Info info { NativeSymbolDebuggingContext::New(), stream };
298+
Info info { NativeSymbolDebuggingContext::New(), stream, 0 };
298299

299-
fprintf(stream, "uv loop at [%p] has %d active handles\n",
300-
loop, loop->active_handles);
300+
fprintf(stream, "uv loop at [%p] has open handles:\n", loop);
301301

302302
uv_walk(loop, [](uv_handle_t* handle, void* arg) {
303303
Info* info = static_cast<Info*>(arg);
304304
NativeSymbolDebuggingContext* sym_ctx = info->ctx.get();
305305
FILE* stream = info->stream;
306+
info->num_handles++;
306307

307-
fprintf(stream, "[%p] %s\n", handle, uv_handle_type_name(handle->type));
308+
fprintf(stream, "[%p] %s%s\n", handle, uv_handle_type_name(handle->type),
309+
uv_is_active(handle) ? " (active)" : "");
308310

309311
void* close_cb = reinterpret_cast<void*>(handle->close_cb);
310312
fprintf(stream, "\tClose callback: %p %s\n",
@@ -328,6 +330,9 @@ void PrintLibuvHandleInformation(uv_loop_t* loop, FILE* stream) {
328330
first_field, sym_ctx->LookupSymbol(first_field).Display().c_str());
329331
}
330332
}, &info);
333+
334+
fprintf(stream, "uv loop at [%p] has %zu open handles in total\n",
335+
loop, info.num_handles);
331336
}
332337

333338
std::vector<std::string> NativeSymbolDebuggingContext::GetLoadedLibraries() {

test/abort/test-addon-uv-handle-leak.js

+15-10
Original file line numberDiff line numberDiff line change
@@ -47,8 +47,8 @@ if (process.argv[2] === 'child') {
4747

4848
// Parse output that is formatted like this:
4949

50-
// uv loop at [0x559b65ed5770] has active handles
51-
// [0x7f2de0018430] timer
50+
// uv loop at [0x559b65ed5770] has open handles:
51+
// [0x7f2de0018430] timer (active)
5252
// Close callback: 0x7f2df31de220 CloseCallback(uv_handle_s*) [...]
5353
// Data: 0x7f2df33df140 example_instance [...]
5454
// (First field): 0x7f2df33dedc0 vtable for ExampleOwnerClass [...]
@@ -58,6 +58,7 @@ if (process.argv[2] === 'child') {
5858
// [0x7f2de000b910] timer
5959
// Close callback: 0x7f2df31de220 CloseCallback(uv_handle_s*) [...]
6060
// Data: 0x42
61+
// uv loop at [0x559b65ed5770] has 3 open handles in total
6162

6263
function isGlibc() {
6364
try {
@@ -89,15 +90,15 @@ if (process.argv[2] === 'child') {
8990

9091
switch (state) {
9192
case 'initial':
92-
assert(/^uv loop at \[.+\] has \d+ active handles$/.test(line), line);
93+
assert(/^uv loop at \[.+\] has open handles:$/.test(line), line);
9394
state = 'handle-start';
9495
break;
9596
case 'handle-start':
96-
if (/Assertion .+ failed/.test(line)) {
97-
state = 'done';
97+
if (/^uv loop at \[.+\] has \d+ open handles in total$/.test(line)) {
98+
state = 'assertion-failure';
9899
break;
99100
}
100-
assert(/^\[.+\] timer$/.test(line), line);
101+
assert(/^\[.+\] timer( \(active\))?$/.test(line), line);
101102
state = 'close-callback';
102103
break;
103104
case 'close-callback':
@@ -109,15 +110,19 @@ if (process.argv[2] === 'child') {
109110
state = 'maybe-first-field';
110111
break;
111112
case 'maybe-first-field':
112-
if (/^\(First field\)$/.test(line)) {
113+
if (!/^\(First field\)/.test(line)) {
113114
lines.unshift(line);
114-
state = 'handle-start';
115-
break;
116115
}
117-
state = 'maybe-first-field';
116+
state = 'handle-start';
117+
break;
118+
case 'assertion-failure':
119+
assert(/Assertion .+ failed/.test(line), line);
120+
state = 'done';
118121
break;
119122
case 'done':
120123
break;
121124
}
122125
}
126+
127+
assert.strictEqual(state, 'done');
123128
}

0 commit comments

Comments
 (0)