libmain: Make the entire stack overflow handler pluggable

This commit is contained in:
Robert Hensing 2022-10-14 12:37:34 +02:00
parent 0d75675787
commit ab4eb39386
2 changed files with 12 additions and 11 deletions

View file

@ -113,14 +113,15 @@ struct PrintFreed
/* Install a SIGSEGV handler to detect stack overflows. */ /* Install a SIGSEGV handler to detect stack overflows. */
void detectStackOverflow(); void detectStackOverflow();
/* Pluggable behavior to run before _exit(1) in case of a stack overflow. /* Pluggable behavior to run in case of a stack overflow.
Default value: do nothing, return immediately. Default value: defaultStackOverflowHandler.
This is called by the handler installed by detectStackOverflow(). This is called by the handler installed by detectStackOverflow().
This gives Nix library consumers a limit opportunity to report the error This gives Nix library consumers a limit opportunity to report the error
condition. condition. The handler should exit the process.
See defaultStackOverflowHandler() for a reference implementation.
NOTE: Use with diligence, because this runs in the signal handler, with very NOTE: Use with diligence, because this runs in the signal handler, with very
limited stack space and a potentially a corrupted heap, all while the failed limited stack space and a potentially a corrupted heap, all while the failed

View file

@ -30,10 +30,7 @@ static void sigsegvHandler(int signo, siginfo_t * info, void * ctx)
ptrdiff_t diff = (char *) info->si_addr - sp; ptrdiff_t diff = (char *) info->si_addr - sp;
if (diff < 0) diff = -diff; if (diff < 0) diff = -diff;
if (diff < 4096) { if (diff < 4096) {
char msg[] = "error: stack overflow (possible infinite recursion)\n"; nix::stackOverflowHandler(info, ctx);
[[gnu::unused]] auto res = write(2, msg, strlen(msg));
nix::extraStackOverflowHandler(info, ctx);
_exit(1); // maybe abort instead?
} }
} }
@ -69,9 +66,12 @@ void detectStackOverflow()
#endif #endif
} }
std::function<void(siginfo_t * info, void * ctx)> extraStackOverflowHandler( std::function<void(siginfo_t * info, void * ctx)> stackOverflowHandler(defaultStackOverflowHandler);
[](siginfo_t * info, void * ctx) {
void defaultStackOverflowHandler(siginfo_t * info, void * ctx) {
char msg[] = "error: stack overflow (possible infinite recursion)\n";
[[gnu::unused]] auto res = write(2, msg, strlen(msg));
_exit(1); // maybe abort instead?
} }
);
} }