From: Simon McVittie Date: Fri, 6 Dec 2019 01:54:18 +0000 (+0100) Subject: _dbus_modify_sigpipe: be thread-safe X-Git-Tag: dbus-1.13.14~20^2~1 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=bf20f7387381d1bba0a261f6f0a849c0df5d7e1a;p=thirdparty%2Fdbus.git _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. --- diff --git a/dbus/dbus-connection.c b/dbus/dbus-connection.c index 0b6a0c6d5..159dbe1b6 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 1eb54bd49..c91c05ef4 100644 --- a/dbus/dbus-sysdeps-unix.c +++ b/dbus/dbus-sysdeps-unix.c @@ -3071,6 +3071,42 @@ _dbus_atomic_get (DBusAtomic *atomic) #endif } +/** + * 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(). * diff --git a/dbus/dbus-sysdeps-win.c b/dbus/dbus-sysdeps-win.c index 46cbfe355..c5a9d0168 100644 --- a/dbus/dbus-sysdeps-win.c +++ b/dbus/dbus-sysdeps-win.c @@ -3298,6 +3298,28 @@ _dbus_atomic_get (DBusAtomic *atomic) return atomic->value; } +/** + * 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 diff --git a/dbus/dbus-sysdeps.h b/dbus/dbus-sysdeps.h index 7c4204264..60091026a 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