From dd945345715b90b2a1db769865c79d86a1dfad06 Mon Sep 17 00:00:00 2001 From: Brad King Date: Sat, 23 Dec 2017 08:01:11 -0500 Subject: cmCTestMultiProcessHandler: Add helper to make libuv use SA_RESTART Prior to 1.19, libuv does not use SA_RESTART in its signal handler. Add a helper to cause libuv to install its handler and then revise the handler's flags to add SA_RESTART. --- Source/CTest/cmCTestMultiProcessHandler.cxx | 37 +++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/Source/CTest/cmCTestMultiProcessHandler.cxx b/Source/CTest/cmCTestMultiProcessHandler.cxx index 6cdec8d..4a980d7 100644 --- a/Source/CTest/cmCTestMultiProcessHandler.cxx +++ b/Source/CTest/cmCTestMultiProcessHandler.cxx @@ -22,6 +22,43 @@ #include #include +#if defined(CMAKE_USE_SYSTEM_LIBUV) && !defined(_WIN32) && \ + UV_VERSION_MAJOR == 1 && UV_VERSION_MINOR < 19 +#define CMAKE_UV_SIGNAL_HACK +/* + libuv does not use SA_RESTART on its signal handler, but C++ streams + depend on it for reliable i/o operations. This RAII helper convinces + libuv to install its handler, and then revises the handler to add the + SA_RESTART flag. We use a distinct uv loop that never runs to avoid + ever really getting a callback. libuv may fill the hack loop's signal + pipe and then stop writing, but that won't break any real loops. + */ +class cmUVSignalHackRAII +{ + uv_loop_t HackLoop; + cm::uv_signal_ptr HackSignal; + static void HackCB(uv_signal_t*, int) {} +public: + cmUVSignalHackRAII() + { + uv_loop_init(&this->HackLoop); + this->HackSignal.init(this->HackLoop); + this->HackSignal.start(HackCB, SIGCHLD); + struct sigaction hack_sa; + sigaction(SIGCHLD, NULL, &hack_sa); + if (!(hack_sa.sa_flags & SA_RESTART)) { + hack_sa.sa_flags |= SA_RESTART; + sigaction(SIGCHLD, &hack_sa, NULL); + } + } + ~cmUVSignalHackRAII() + { + this->HackSignal.stop(); + uv_loop_close(&this->HackLoop); + } +}; +#endif + class TestComparator { public: -- cgit v0.12