libmain: Add extraStackOverflowHandler

This commit is contained in:
Robert Hensing 2022-10-14 12:25:41 +02:00
parent 8196d4f4e9
commit 0d75675787
2 changed files with 25 additions and 0 deletions

View file

@ -113,5 +113,24 @@ 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.
Default value: do nothing, return immediately.
This is called by the handler installed by detectStackOverflow().
This gives Nix library consumers a limit opportunity to report the error
condition.
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
thread is blocked indefinitely. All functions called must be reentrant. */
extern std::function<void(siginfo_t * info, void * ctx)> stackOverflowHandler;
/* The default, robust implementation of stackOverflowHandler.
Prints an error message directly to stderr using a syscall instead of the
logger. Exits the process immediately after. */
void defaultStackOverflowHandler(siginfo_t * info, void * ctx);
} }

View file

@ -1,4 +1,5 @@
#include "error.hh" #include "error.hh"
#include "shared.hh"
#include <cstring> #include <cstring>
#include <cstddef> #include <cstddef>
@ -31,6 +32,7 @@ static void sigsegvHandler(int signo, siginfo_t * info, void * ctx)
if (diff < 4096) { if (diff < 4096) {
char msg[] = "error: stack overflow (possible infinite recursion)\n"; char msg[] = "error: stack overflow (possible infinite recursion)\n";
[[gnu::unused]] auto res = write(2, msg, strlen(msg)); [[gnu::unused]] auto res = write(2, msg, strlen(msg));
nix::extraStackOverflowHandler(info, ctx);
_exit(1); // maybe abort instead? _exit(1); // maybe abort instead?
} }
} }
@ -67,5 +69,9 @@ void detectStackOverflow()
#endif #endif
} }
std::function<void(siginfo_t * info, void * ctx)> extraStackOverflowHandler(
[](siginfo_t * info, void * ctx) {
}
);
} }