_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.
This commit is contained in:
Simon McVittie 2019-12-06 02:54:18 +01:00 committed by Ralf Habacker
parent 4e3d6bffe2
commit bf20f73873
4 changed files with 70 additions and 5 deletions

View file

@ -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);
}
/**

View file

@ -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().
*

View file

@ -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

View file

@ -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