summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSimon McVittie <smcv@collabora.com>2019-12-06 02:54:18 +0100
committerRalf Habacker <ralf.habacker@freenet.de>2019-12-12 09:36:32 +0100
commitbf20f7387381d1bba0a261f6f0a849c0df5d7e1a (patch)
tree22897bc8aa632c6ea9139f8db81035fb1fd8306b
parent4e3d6bffe26039d694e44a12d31d9db35e5183c0 (diff)
_dbus_modify_sigpipe: be thread-safe
This needs new atomic primitives: we don't have "set to a value", and in fact that's a bit annoying to implement in terms of gcc intrinsics. "Set to 0" and "set to nonzero" are easy, though.
-rw-r--r--dbus/dbus-connection.c13
-rw-r--r--dbus/dbus-sysdeps-unix.c36
-rw-r--r--dbus/dbus-sysdeps-win.c22
-rw-r--r--dbus/dbus-sysdeps.h4
4 files changed, 70 insertions, 5 deletions
diff --git a/dbus/dbus-connection.c b/dbus/dbus-connection.c
index 0b6a0c6d..159dbe1b 100644
--- a/dbus/dbus-connection.c
+++ b/dbus/dbus-connection.c
@@ -245,9 +245,9 @@ struct DBusPreallocatedSend
};
#if HAVE_DECL_MSG_NOSIGNAL
-static dbus_bool_t _dbus_modify_sigpipe = FALSE;
+static DBusAtomic _dbus_modify_sigpipe = { FALSE };
#else
-static dbus_bool_t _dbus_modify_sigpipe = TRUE;
+static DBusAtomic _dbus_modify_sigpipe = { TRUE };
#endif
/**
@@ -1328,7 +1328,7 @@ _dbus_connection_new_for_transport (DBusTransport *transport)
if (objects == NULL)
goto error;
- if (_dbus_modify_sigpipe)
+ if (_dbus_atomic_get (&_dbus_modify_sigpipe) != 0)
_dbus_disable_sigpipe ();
/* initialized to 0: use atomic op to avoid mixing atomic and non-atomic */
@@ -6115,8 +6115,11 @@ dbus_connection_get_data (DBusConnection *connection,
*/
void
dbus_connection_set_change_sigpipe (dbus_bool_t will_modify_sigpipe)
-{
- _dbus_modify_sigpipe = will_modify_sigpipe != FALSE;
+{
+ if (will_modify_sigpipe)
+ _dbus_atomic_set_nonzero (&_dbus_modify_sigpipe);
+ else
+ _dbus_atomic_set_zero (&_dbus_modify_sigpipe);
}
/**
diff --git a/dbus/dbus-sysdeps-unix.c b/dbus/dbus-sysdeps-unix.c
index 1eb54bd4..c91c05ef 100644
--- a/dbus/dbus-sysdeps-unix.c
+++ b/dbus/dbus-sysdeps-unix.c
@@ -3072,6 +3072,42 @@ _dbus_atomic_get (DBusAtomic *atomic)
}
/**
+ * Atomically set the value of an integer to 0.
+ *
+ * @param atomic pointer to the integer to set
+ */
+void
+_dbus_atomic_set_zero (DBusAtomic *atomic)
+{
+#if DBUS_USE_SYNC
+ /* Atomic version of "*atomic &= 0; return *atomic" */
+ __sync_and_and_fetch (&atomic->value, 0);
+#else
+ pthread_mutex_lock (&atomic_mutex);
+ atomic->value = 0;
+ pthread_mutex_unlock (&atomic_mutex);
+#endif
+}
+
+/**
+ * Atomically set the value of an integer to something nonzero.
+ *
+ * @param atomic pointer to the integer to set
+ */
+void
+_dbus_atomic_set_nonzero (DBusAtomic *atomic)
+{
+#if DBUS_USE_SYNC
+ /* Atomic version of "*atomic |= 1; return *atomic" */
+ __sync_or_and_fetch (&atomic->value, 1);
+#else
+ pthread_mutex_lock (&atomic_mutex);
+ atomic->value = 1;
+ pthread_mutex_unlock (&atomic_mutex);
+#endif
+}
+
+/**
* Wrapper for poll().
*
* @param fds the file descriptors to poll
diff --git a/dbus/dbus-sysdeps-win.c b/dbus/dbus-sysdeps-win.c
index 46cbfe35..c5a9d016 100644
--- a/dbus/dbus-sysdeps-win.c
+++ b/dbus/dbus-sysdeps-win.c
@@ -3299,6 +3299,28 @@ _dbus_atomic_get (DBusAtomic *atomic)
}
/**
+ * Atomically set the value of an integer to 0.
+ *
+ * @param atomic pointer to the integer to set
+ */
+void
+_dbus_atomic_set_zero (DBusAtomic *atomic)
+{
+ InterlockedExchange (&atomic->value, 0);
+}
+
+/**
+ * Atomically set the value of an integer to something nonzero.
+ *
+ * @param atomic pointer to the integer to set
+ */
+void
+_dbus_atomic_set_nonzero (DBusAtomic *atomic)
+{
+ InterlockedExchange (&atomic->value, 1);
+}
+
+/**
* Called when the bus daemon is signaled to reload its configuration; any
* caches should be nuked. Of course any caches that need explicit reload
* are probably broken, but c'est la vie.
diff --git a/dbus/dbus-sysdeps.h b/dbus/dbus-sysdeps.h
index 7c420426..60091026 100644
--- a/dbus/dbus-sysdeps.h
+++ b/dbus/dbus-sysdeps.h
@@ -335,6 +335,10 @@ DBUS_PRIVATE_EXPORT
dbus_int32_t _dbus_atomic_dec (DBusAtomic *atomic);
DBUS_PRIVATE_EXPORT
dbus_int32_t _dbus_atomic_get (DBusAtomic *atomic);
+DBUS_PRIVATE_EXPORT
+void _dbus_atomic_set_zero (DBusAtomic *atomic);
+DBUS_PRIVATE_EXPORT
+void _dbus_atomic_set_nonzero (DBusAtomic *atomic);
#ifdef DBUS_WIN