-
Notifications
You must be signed in to change notification settings - Fork 29.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
src: fix backtrace with [[noreturn]] abort #50849
Conversation
A function tail calls [[noreturn]] node::Abort will print an incorrect call stack because the frame pc was advanced when calling node::Abort to an invalid op, which may vary on different platforms. Dumps the backtrace in the ABORT macro instead to avoid calling backtrace in a tail [[noreturn]] call. Removes the [[noreturn]] attribute if a function calls backtrace and may be called as a tail statement. [[noreturn]] attribute of public functions like `napi_fatal_error` and `node::OnFatalError` can not be removed as compilers may complain about no return values after the removal.
By the way does it matter if abort is tail called or not? I think as long as the caller is marked as [[noreturn]], the compiler is completely free to just not maintain the frame pointer/link register for backtrace (it seems LLVM is particularly eager to do this which I guess is why we are seeing this showing up more on macOS). So the rule of thumb here is to just not mark |
I checked different call sites and their generated code, and I found that a tail call to MaybeLocal<String> BuiltinLoader::LoadBuiltinSource(Isolate* isolate,
const char* id) const {
auto source = source_.read();
const auto source_it = source->find(id);
if (UNLIKELY(source_it == source->end())) {
fprintf(stderr, "Cannot find native builtin: \"%s\".\n", id);
node::Abort();
}
return source_it->second.ToStringChecked(isolate);
} But, yes, the rule should be that we should not mark functions as |
@legendecas Do you have time to address the comments? test-worker-nearheaplimit-deadlock has been haunting the CI for some time, so I'd like to see this landed soon-ish to get some more information out of the flakes. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM with a suggestion to comments
Co-authored-by: Joyee Cheung <joyeec9h3@gmail.com>
Landed in 16a5479 |
A function tail calls [[noreturn]] node::Abort will print an incorrect call stack because the frame pc was advanced when calling node::Abort to an invalid op, which may vary on different platforms. Dumps the backtrace in the ABORT macro instead to avoid calling backtrace in a tail [[noreturn]] call. Removes the [[noreturn]] attribute if a function calls backtrace and may be called as a tail statement. [[noreturn]] attribute of public functions like `napi_fatal_error` and `node::OnFatalError` can not be removed as compilers may complain about no return values after the removal. PR-URL: #50849 Refs: #50761 Reviewed-By: Joyee Cheung <joyeec9h3@gmail.com>
A function tail calls [[noreturn]] node::Abort will print an incorrect call stack because the frame pc was advanced when calling node::Abort to an invalid op, which may vary on different platforms. Dumps the backtrace in the ABORT macro instead to avoid calling backtrace in a tail [[noreturn]] call. Removes the [[noreturn]] attribute if a function calls backtrace and may be called as a tail statement. [[noreturn]] attribute of public functions like `napi_fatal_error` and `node::OnFatalError` can not be removed as compilers may complain about no return values after the removal. PR-URL: #50849 Refs: #50761 Reviewed-By: Joyee Cheung <joyeec9h3@gmail.com>
Actually I noticed in https://ci.nodejs.org/job/node-test-binary-windows-js-suites/26795/RUN_SUBSET=1,nodes=win2022-COMPILED_BY-vs2022/console that this change is breaking most of the places being converted to use int MyFunction(int value) {
if (value >= 0) {
return value;
}
// if Abort is not marked as [[noreturn]], compiler
// will complain about no return value in this branch.
Abort();
}; In this case the function should be rewritten like this: int MyFunction(int value) {
if (value < 0) {
Abort();
}
return value;
}; Otherwise every caller of the |
Oh wait, I think I got it the other way around. Callers of |
@joyeecheung sorry, but the link you provided didn't report a compiler error. Is the link correct? |
The issue is in the crashed test-buffer-isascii with incorrect native stack traces, what we originally tried to fix |
A function calls [[noreturn]] node::Abort will print an incorrect
call stack because the frame pc was advanced to an invalid op
when calling node::Abort, which may vary on different platforms.
Dumps the backtrace in the ABORT macro instead to avoid calling
backtrace in a [[noreturn]] call. Removes the [[noreturn]]
attribute if a function calls backtrace.
[[noreturn]] attribute of public functions like
napi_fatal_error
andnode::OnFatalError
can not be removed as compilers may complainabout no return values after the removal.
Refs: #50761