Fix thread-safety of qt_ignore_sigpipe
authorThiago Macieira <thiago.macieira@intel.com>
Tue, 11 Sep 2012 13:36:54 +0000 (15:36 +0200)
committerThe Qt Project <gerrit-noreply@qt-project.org>
Tue, 18 Sep 2012 12:11:53 +0000 (14:11 +0200)
The testAndSet operation would mean another thread could see the value
of 1 and proceed to write(2)/sendto(2) before SIGPIPE had been ignored.
If the pipe or socket were already closed by then, a SIGPIPE would be
delivered to the application with its default action: terminate.

Change-Id: I62dc8f5fa14c1dd453d13e4053c642bd78fbc468
Reviewed-by: Qt Doc Bot <qt_docbot@qt-project.org>
Reviewed-by: Oswald Buddenhagen <oswald.buddenhagen@digia.com>
Reviewed-by: Shane Kearns <shane.kearns@accenture.com>
Reviewed-by: Peter Hartmann <phartmann@rim.com>
src/corelib/io/qprocess_unix.cpp
src/network/socket/qnativesocketengine_unix.cpp

index d3c2cd9..137702c 100644 (file)
@@ -953,11 +953,15 @@ static void qt_ignore_sigpipe()
 {
     // Set to ignore SIGPIPE once only.
     static QBasicAtomicInt atom = Q_BASIC_ATOMIC_INITIALIZER(0);
-    if (atom.testAndSetRelaxed(0, 1)) {
+    if (!atom.load()) {
+        // More than one thread could turn off SIGPIPE at the same time
+        // But that's acceptable because they all would be doing the same
+        // action
         struct sigaction noaction;
         memset(&noaction, 0, sizeof(noaction));
         noaction.sa_handler = SIG_IGN;
         ::sigaction(SIGPIPE, &noaction, 0);
+        atom.store(1);
     }
 }
 
index 4b22f1c..c73bbed 100644 (file)
@@ -103,11 +103,15 @@ static void qt_ignore_sigpipe()
 #ifndef Q_NO_POSIX_SIGNALS
     // Set to ignore SIGPIPE once only.
     static QBasicAtomicInt atom = Q_BASIC_ATOMIC_INITIALIZER(0);
-    if (atom.testAndSetRelaxed(0, 1)) {
+    if (!atom.load()) {
+        // More than one thread could turn off SIGPIPE at the same time
+        // But that's acceptable because they all would be doing the same
+        // action
         struct sigaction noaction;
         memset(&noaction, 0, sizeof(noaction));
         noaction.sa_handler = SIG_IGN;
         ::sigaction(SIGPIPE, &noaction, 0);
+        atom.store(1);
     }
 #else
     // Posix signals are not supported by the underlying platform