fork(1) download
  1. #include <chrono>
  2. #include <condition_variable>
  3. #include <csignal>
  4. #include <cstdint>
  5. #include <cstdio>
  6. #include <cstdlib>
  7. #include <exception>
  8. #include <initializer_list>
  9. #include <mutex>
  10. #include <setjmp.h>
  11. #include <stdexcept>
  12. #include <thread>
  13.  
  14. // Missing set_unexpected / unexpected_handler, violating noexcept, violating exception specification, parallel algorithms leaving with uncaught exception.
  15.  
  16. #define LOG(msg, ...) fprintf(stderr, msg "\n", ##__VA_ARGS__)
  17.  
  18. sigjmp_buf jmpbuf;
  19. volatile intptr_t zero = 0;
  20. bool thread_done = false;
  21. std::mutex m;
  22. std::condition_variable cv;
  23.  
  24. int main() try {
  25. std::thread t([]() {
  26. for (auto sig : {SIGTERM, SIGSEGV, SIGINT, SIGILL, SIGABRT, SIGFPE})
  27. std::signal(sig, [](int sig) {
  28. switch (sig) {
  29. case SIGTERM: LOG("\tSIGTERM"); break;
  30. case SIGSEGV: LOG("\tSIGSEGV"); break;
  31. case SIGINT: LOG("\tSIGINT"); break;
  32. case SIGILL: LOG("\tSIGILL"); break;
  33. case SIGABRT: LOG("\tSIGABRT"); break;
  34. case SIGFPE: LOG("\tSIGFPE"); break;
  35. default: LOG("Unknown signal %i", sig);
  36. }
  37. siglongjmp(jmpbuf, sig);
  38. });
  39. std::at_quick_exit([] { LOG("\tQuick exiting"); throw std::runtime_error("from quick exit"); });
  40. std::atexit([] { LOG("\tExiting"); quick_exit(0); });
  41. std::set_terminate([] { LOG("\tTerminating"); exit(0); });
  42.  
  43. int handling = 0;
  44. handling = sigsetjmp(jmpbuf, 1);
  45. switch (handling) {
  46. case SIGTERM: LOG("deref zero"); *(int*)zero = 0;
  47. case SIGSEGV: LOG("raising INT"); std::raise(SIGINT);
  48. case SIGINT: LOG("executing illegal instr"); asm("ud2");
  49. case SIGILL: LOG("dividing by zero"); *(int*)zero = 1337 / zero;
  50. case SIGABRT: LOG("raising TERM"); std::raise(SIGTERM);
  51. case SIGFPE: LOG("OK that's enough signaling"); break;
  52. default: LOG("Unknown handling %i", handling);
  53. case 0:
  54. LOG("Going to terminate");
  55. throw std::runtime_error("from thread");
  56. }
  57.  
  58. { std::lock_guard<std::mutex> lock(m); thread_done = true; }
  59. cv.notify_one();
  60. for (;;) std::this_thread::sleep_for(std::chrono::seconds(1));
  61. });
  62.  
  63. std::unique_lock<std::mutex> lock(m);
  64. cv.wait(lock, [] { return thread_done; });
  65. LOG("main notified that thread is done");
  66.  
  67. throw std::runtime_error("from main");
  68. return 0;
  69. } catch (const std::exception &e) {
  70. LOG("Caught '%s'", e.what());
  71. throw;
  72. }
Success #stdin #stdout #stderr 0s 6544KB
stdin
Standard input is empty
stdout
Standard output is empty
stderr
Going to terminate
	Terminating
	Exiting
	Quick exiting
	SIGABRT
raising TERM
	SIGTERM
deref zero
	SIGSEGV
raising INT
	SIGINT
executing illegal instr
	SIGILL
dividing by zero
	SIGFPE
OK that's enough signaling
main notified that thread is done
	Terminating