summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMathis Beer <Mathis.Beer@funkwerk-itk.com>2020-03-12 06:37:05 +0100
committerMathis Beer <Mathis.Beer@funkwerk-itk.com>2020-03-12 06:49:29 +0100
commita12ca58dfa4db8de1045117c8994b423a9802da4 (patch)
tree1e665380b2a17c8da4f4dd4aac364c82e3dd370e
parentb4dea2ef9b529e2a7fb8619d68f0830ff957d3de (diff)
downloadlibfaketime-a12ca58dfa4db8de1045117c8994b423a9802da4.tar.gz
fix threading issue: don't assign to the global lock state struct until we're safely inside the mutex.
Otherwise, we might be overwriting the global lock state from two different threads at once.
-rw-r--r--src/libfaketime.c8
1 files changed, 5 insertions, 3 deletions
diff --git a/src/libfaketime.c b/src/libfaketime.c
index 17ebaa2..c259240 100644
--- a/src/libfaketime.c
+++ b/src/libfaketime.c
@@ -2636,8 +2636,9 @@ struct LockedState {
static void pthread_cleanup_mutex_lock(void *data)
{
struct LockedState *state = data;
+ sigset_t original_mask = state->original_mask; // inside the lock!
pthread_mutex_unlock(&state->mutex);
- pthread_sigmask(SIG_SETMASK, &state->original_mask, NULL);
+ pthread_sigmask(SIG_SETMASK, &original_mask, NULL);
}
#endif
@@ -2673,10 +2674,11 @@ int fake_clock_gettime(clockid_t clk_id, struct timespec *tp)
static struct LockedState state = { 0 };
// block all signals while locked. prevents deadlocks if signal interrupts in in mid-operation.
- sigset_t all_signals;
+ sigset_t all_signals, original_mask;
sigfillset(&all_signals);
- pthread_sigmask(SIG_SETMASK, &all_signals, &state.original_mask);
+ pthread_sigmask(SIG_SETMASK, &all_signals, &original_mask);
pthread_mutex_lock(&state.mutex);
+ state.original_mask = original_mask; // inside the lock!
pthread_cleanup_push(pthread_cleanup_mutex_lock, &state);
#endif