src: add PrintLibuvHandleInformation debug helper
This function is not only helpful for debugging crashes, but can also be used as an ad-hoc debugging statement. PR-URL: https://github.com/nodejs/node/pull/25905 Reviewed-By: Colin Ihrig <cjihrig@gmail.com> Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl> Reviewed-By: James M Snell <jasnell@gmail.com>
This commit is contained in:
parent
2ed556c11f
commit
46d9573c68
@ -282,20 +282,36 @@ void DumpBacktrace(FILE* fp) {
|
|||||||
void CheckedUvLoopClose(uv_loop_t* loop) {
|
void CheckedUvLoopClose(uv_loop_t* loop) {
|
||||||
if (uv_loop_close(loop) == 0) return;
|
if (uv_loop_close(loop) == 0) return;
|
||||||
|
|
||||||
auto sym_ctx = NativeSymbolDebuggingContext::New();
|
PrintLibuvHandleInformation(loop, stderr);
|
||||||
|
|
||||||
fprintf(stderr, "uv loop at [%p] has active handles\n", loop);
|
fflush(stderr);
|
||||||
|
// Finally, abort.
|
||||||
|
CHECK(0 && "uv_loop_close() while having open handles");
|
||||||
|
}
|
||||||
|
|
||||||
|
void PrintLibuvHandleInformation(uv_loop_t* loop, FILE* stream) {
|
||||||
|
struct Info {
|
||||||
|
std::unique_ptr<NativeSymbolDebuggingContext> ctx;
|
||||||
|
FILE* stream;
|
||||||
|
};
|
||||||
|
|
||||||
|
Info info { NativeSymbolDebuggingContext::New(), stream };
|
||||||
|
|
||||||
|
fprintf(stream, "uv loop at [%p] has %d active handles\n",
|
||||||
|
loop, loop->active_handles);
|
||||||
|
|
||||||
uv_walk(loop, [](uv_handle_t* handle, void* arg) {
|
uv_walk(loop, [](uv_handle_t* handle, void* arg) {
|
||||||
auto sym_ctx = static_cast<NativeSymbolDebuggingContext*>(arg);
|
Info* info = static_cast<Info*>(arg);
|
||||||
|
NativeSymbolDebuggingContext* sym_ctx = info->ctx.get();
|
||||||
|
FILE* stream = info->stream;
|
||||||
|
|
||||||
fprintf(stderr, "[%p] %s\n", handle, uv_handle_type_name(handle->type));
|
fprintf(stream, "[%p] %s\n", handle, uv_handle_type_name(handle->type));
|
||||||
|
|
||||||
void* close_cb = reinterpret_cast<void*>(handle->close_cb);
|
void* close_cb = reinterpret_cast<void*>(handle->close_cb);
|
||||||
fprintf(stderr, "\tClose callback: %p %s\n",
|
fprintf(stream, "\tClose callback: %p %s\n",
|
||||||
close_cb, sym_ctx->LookupSymbol(close_cb).Display().c_str());
|
close_cb, sym_ctx->LookupSymbol(close_cb).Display().c_str());
|
||||||
|
|
||||||
fprintf(stderr, "\tData: %p %s\n",
|
fprintf(stream, "\tData: %p %s\n",
|
||||||
handle->data, sym_ctx->LookupSymbol(handle->data).Display().c_str());
|
handle->data, sym_ctx->LookupSymbol(handle->data).Display().c_str());
|
||||||
|
|
||||||
// We are also interested in the first field of what `handle->data`
|
// We are also interested in the first field of what `handle->data`
|
||||||
@ -309,14 +325,10 @@ void CheckedUvLoopClose(uv_loop_t* loop) {
|
|||||||
first_field = *reinterpret_cast<void**>(handle->data);
|
first_field = *reinterpret_cast<void**>(handle->data);
|
||||||
|
|
||||||
if (first_field != nullptr) {
|
if (first_field != nullptr) {
|
||||||
fprintf(stderr, "\t(First field): %p %s\n",
|
fprintf(stream, "\t(First field): %p %s\n",
|
||||||
first_field, sym_ctx->LookupSymbol(first_field).Display().c_str());
|
first_field, sym_ctx->LookupSymbol(first_field).Display().c_str());
|
||||||
}
|
}
|
||||||
}, sym_ctx.get());
|
}, &info);
|
||||||
|
|
||||||
fflush(stderr);
|
|
||||||
// Finally, abort.
|
|
||||||
CHECK(0 && "uv_loop_close() while having open handles");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::string> NativeSymbolDebuggingContext::GetLoadedLibraries() {
|
std::vector<std::string> NativeSymbolDebuggingContext::GetLoadedLibraries() {
|
||||||
|
@ -119,6 +119,7 @@ class NativeSymbolDebuggingContext {
|
|||||||
// about giving information on currently existing handles, if there are any,
|
// about giving information on currently existing handles, if there are any,
|
||||||
// but still aborts the process.
|
// but still aborts the process.
|
||||||
void CheckedUvLoopClose(uv_loop_t* loop);
|
void CheckedUvLoopClose(uv_loop_t* loop);
|
||||||
|
void PrintLibuvHandleInformation(uv_loop_t* loop, FILE* stream);
|
||||||
|
|
||||||
} // namespace node
|
} // namespace node
|
||||||
|
|
||||||
|
@ -89,7 +89,7 @@ if (process.argv[2] === 'child') {
|
|||||||
|
|
||||||
switch (state) {
|
switch (state) {
|
||||||
case 'initial':
|
case 'initial':
|
||||||
assert(/^uv loop at \[.+\] has active handles$/.test(line), line);
|
assert(/^uv loop at \[.+\] has \d+ active handles$/.test(line), line);
|
||||||
state = 'handle-start';
|
state = 'handle-start';
|
||||||
break;
|
break;
|
||||||
case 'handle-start':
|
case 'handle-start':
|
||||||
|
Loading…
x
Reference in New Issue
Block a user