src: fix backtrace with [[noreturn]] abort#50849
src: fix backtrace with [[noreturn]] abort#50849nodejs-github-bot merged 4 commits intonodejs:mainfrom
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. |
joyeecheung
left a comment
There was a problem hiding this comment.
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_errorandnode::OnFatalErrorcan not be removed as compilers may complainabout no return values after the removal.
Refs: #50761