aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorRobert Hensing <robert@roberthensing.nl>2022-10-14 12:25:41 +0200
committerRobert Hensing <robert@roberthensing.nl>2022-10-14 12:53:07 +0200
commit0d756757877ecfb09fd2003cf887dfdf8067b702 (patch)
tree2ebc6430b10822e4338873defea2b2e2c84a5f89 /src
parent8196d4f4e94407396b4ba37bd89c91ad0d4062f0 (diff)
libmain: Add extraStackOverflowHandler
Diffstat (limited to 'src')
-rw-r--r--src/libmain/shared.hh19
-rw-r--r--src/libmain/stack.cc6
2 files changed, 25 insertions, 0 deletions
diff --git a/src/libmain/shared.hh b/src/libmain/shared.hh
index 0cc56d47d..66d29a1f7 100644
--- a/src/libmain/shared.hh
+++ b/src/libmain/shared.hh
@@ -113,5 +113,24 @@ struct PrintFreed
/* Install a SIGSEGV handler to detect stack overflows. */
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);
}
diff --git a/src/libmain/stack.cc b/src/libmain/stack.cc
index b0a4a4c5d..a6d10f738 100644
--- a/src/libmain/stack.cc
+++ b/src/libmain/stack.cc
@@ -1,4 +1,5 @@
#include "error.hh"
+#include "shared.hh"
#include <cstring>
#include <cstddef>
@@ -31,6 +32,7 @@ static void sigsegvHandler(int signo, siginfo_t * info, void * ctx)
if (diff < 4096) {
char msg[] = "error: stack overflow (possible infinite recursion)\n";
[[gnu::unused]] auto res = write(2, msg, strlen(msg));
+ nix::extraStackOverflowHandler(info, ctx);
_exit(1); // maybe abort instead?
}
}
@@ -67,5 +69,9 @@ void detectStackOverflow()
#endif
}
+std::function<void(siginfo_t * info, void * ctx)> extraStackOverflowHandler(
+ [](siginfo_t * info, void * ctx) {
+ }
+);
}