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:
Anna Henningsen 2019-02-03 15:01:36 +01:00
parent 2ed556c11f
commit 46d9573c68
No known key found for this signature in database
GPG Key ID: 9C63F3A6CD2AD8F9
3 changed files with 26 additions and 13 deletions

View File

@ -282,20 +282,36 @@ void DumpBacktrace(FILE* fp) {
void CheckedUvLoopClose(uv_loop_t* loop) {
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) {
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);
fprintf(stderr, "\tClose callback: %p %s\n",
fprintf(stream, "\tClose callback: %p %s\n",
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());
// 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);
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());
}
}, sym_ctx.get());
fflush(stderr);
// Finally, abort.
CHECK(0 && "uv_loop_close() while having open handles");
}, &info);
}
std::vector<std::string> NativeSymbolDebuggingContext::GetLoadedLibraries() {

View File

@ -119,6 +119,7 @@ class NativeSymbolDebuggingContext {
// about giving information on currently existing handles, if there are any,
// but still aborts the process.
void CheckedUvLoopClose(uv_loop_t* loop);
void PrintLibuvHandleInformation(uv_loop_t* loop, FILE* stream);
} // namespace node

View File

@ -89,7 +89,7 @@ if (process.argv[2] === 'child') {
switch (state) {
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';
break;
case 'handle-start':