summaryrefslogtreecommitdiff
path: root/Source/CTest
diff options
context:
space:
mode:
authorBrad King <brad.king@kitware.com>2017-12-23 08:01:11 -0500
committerBrad King <brad.king@kitware.com>2018-01-10 10:18:12 -0500
commitdd945345715b90b2a1db769865c79d86a1dfad06 (patch)
treec3d2095e4579d28959371516e5484c5cbc011385 /Source/CTest
parent7e0eb77f2f0da764ba9d8a4045351bd7799e101d (diff)
downloadcmake-dd945345715b90b2a1db769865c79d86a1dfad06.tar.gz
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.
Diffstat (limited to 'Source/CTest')
-rw-r--r--Source/CTest/cmCTestMultiProcessHandler.cxx37
1 files changed, 37 insertions, 0 deletions
diff --git a/Source/CTest/cmCTestMultiProcessHandler.cxx b/Source/CTest/cmCTestMultiProcessHandler.cxx
index 6cdec8d65b..4a980d7585 100644
--- a/Source/CTest/cmCTestMultiProcessHandler.cxx
+++ b/Source/CTest/cmCTestMultiProcessHandler.cxx
@@ -22,6 +22,43 @@
#include <stdlib.h>
#include <utility>
+#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: