#include <chrono>
#include <condition_variable>
#include <csignal>
#include <cstdint>
#include <cstdio>
#include <cstdlib>
#include <exception>
#include <initializer_list>
#include <mutex>
#include <setjmp.h>
#include <stdexcept>
#include <thread>
// Missing set_unexpected / unexpected_handler, violating noexcept, violating exception specification, parallel algorithms leaving with uncaught exception.
#define LOG(msg, ...) fprintf(stderr, msg "\n", ##__VA_ARGS__)
sigjmp_buf jmpbuf;
volatile intptr_t zero = 0;
bool thread_done = false;
std::mutex m;
std::condition_variable cv;
int main() try {
std::thread t([]() {
for (auto sig : {SIGTERM, SIGSEGV, SIGINT, SIGILL, SIGABRT, SIGFPE})
std::signal(sig, [](int sig) {
switch (sig) {
case SIGTERM: LOG("\tSIGTERM"); break;
case SIGSEGV: LOG("\tSIGSEGV"); break;
case SIGINT: LOG("\tSIGINT"); break;
case SIGILL: LOG("\tSIGILL"); break;
case SIGABRT: LOG("\tSIGABRT"); break;
case SIGFPE: LOG("\tSIGFPE"); break;
default: LOG("Unknown signal %i", sig);
}
siglongjmp(jmpbuf, sig);
});
std::at_quick_exit([] { LOG("\tQuick exiting"); throw std::runtime_error("from quick exit"); });
std::atexit([] { LOG("\tExiting"); quick_exit(0); });
std::set_terminate([] { LOG("\tTerminating"); exit(0); });
int handling = 0;
handling = sigsetjmp(jmpbuf, 1);
switch (handling) {
case SIGTERM: LOG("deref zero"); *(int*)zero = 0;
case SIGSEGV: LOG("raising INT"); std::raise(SIGINT);
case SIGINT: LOG("executing illegal instr"); asm("ud2");
case SIGILL: LOG("dividing by zero"); *(int*)zero = 1337 / zero;
case SIGABRT: LOG("raising TERM"); std::raise(SIGTERM);
case SIGFPE: LOG("OK that's enough signaling"); break;
default: LOG("Unknown handling %i", handling);
case 0:
LOG("Going to terminate");
throw std::runtime_error("from thread");
}
{ std::lock_guard<std::mutex> lock(m); thread_done = true; }
cv.notify_one();
for (;;) std::this_thread::sleep_for(std::chrono::seconds(1));
});
std::unique_lock<std::mutex> lock(m);
cv.wait(lock, [] { return thread_done; });
LOG("main notified that thread is done");
throw std::runtime_error("from main");
return 0;
} catch (const std::exception &e) {
LOG("Caught '%s'", e.what());
throw;
}