cmUVSignalHackRAII.h 1.4 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344
  1. /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
  2. file Copyright.txt or https://cmake.org/licensing for details. */
  3. #pragma once
  4. #include "cmConfigure.h" // IWYU pragma: keep
  5. #include "cm_uv.h"
  6. #if defined(CMAKE_USE_SYSTEM_LIBUV) && !defined(_WIN32) && \
  7. UV_VERSION_MAJOR == 1 && UV_VERSION_MINOR < 19
  8. #define CMAKE_UV_SIGNAL_HACK
  9. #include "cmUVHandlePtr.h"
  10. /*
  11. libuv does not use SA_RESTART on its signal handler, but C++ streams
  12. depend on it for reliable i/o operations. This RAII helper convinces
  13. libuv to install its handler, and then revises the handler to add the
  14. SA_RESTART flag. We use a distinct uv loop that never runs to avoid
  15. ever really getting a callback. libuv may fill the hack loop's signal
  16. pipe and then stop writing, but that won't break any real loops.
  17. */
  18. class cmUVSignalHackRAII
  19. {
  20. uv_loop_t HackLoop;
  21. cm::uv_signal_ptr HackSignal;
  22. static void HackCB(uv_signal_t*, int) {}
  23. public:
  24. cmUVSignalHackRAII()
  25. {
  26. uv_loop_init(&this->HackLoop);
  27. this->HackSignal.init(this->HackLoop);
  28. this->HackSignal.start(HackCB, SIGCHLD);
  29. struct sigaction hack_sa;
  30. sigaction(SIGCHLD, nullptr, &hack_sa);
  31. if (!(hack_sa.sa_flags & SA_RESTART)) {
  32. hack_sa.sa_flags |= SA_RESTART;
  33. sigaction(SIGCHLD, &hack_sa, nullptr);
  34. }
  35. }
  36. ~cmUVSignalHackRAII()
  37. {
  38. this->HackSignal.stop();
  39. uv_loop_close(&this->HackLoop);
  40. }
  41. };
  42. #endif