TSAN Segmentation fault with timer_create and SIGEV_THREAD
Author: janoosthoekCreated Jan 25, 2023Updated Nov 28, 2025
Hi all,
this bug was verified with clang 14 stable release and perhaps someone can point me to my failure.
I was lazy and took this code from https://medium.com/vswe/posix-timer-1502348c2f9f because we use this also in our large scale application and needed a sample test app.
#include <time.h>
#include <signal.h>
#include <pthread.h>
#include <sys/syscall.h>
#include <stdio.h> // printf
#include <assert.h> // assert
#include <unistd.h> // sleep
int expire_count = 0;
pthread_mutex_t mutex;
pthread_cond_t cond;
void timer_thread(__sigval_t sig) {
pid_t tid = syscall(__NR_gettid);
while (1) {
pthread_mutex_lock(&mutex);
expire_count++;
if (expire_count >= 5)
pthread_cond_signal(&cond);
printf("timer thread id: %d, count: %d\n", tid, expire_count);
pthread_mutex_unlock(&mutex);
sleep(1);
}
}
int main(int argc, char **argv) {
pid_t tid = syscall(__NR_gettid);
printf("main thread id: %d\n", tid);
timer_t timer_id;
/* register signal callback */
struct sigevent sev;
sev.sigev_notify = SIGEV_THREAD;
sev.sigev_notify_function = timer_thread;
/* detached thread, can't be joined */
sev.sigev_notify_attributes = NULL;
sev.sigev_value.sival_ptr = &timer_id;
/* create timer */
assert(timer_create(CLOCK_MONOTONIC, &sev, &timer_id) == 0);
/* set time */
long long freq_nanosecs = 1e9;
struct itimerspec its;
its.it_value.tv_sec = freq_nanosecs / 1000000000;
its.it_value.tv_nsec = freq_nanosecs % 100000000;
its.it_interval.tv_sec = its.it_value.tv_sec;
its.it_interval.tv_nsec = its.it_value.tv_nsec;
/* start timer */
timer_settime(timer_id, 0, &its, NULL);
pthread_mutex_lock(&mutex);
while (expire_count < 5) {
printf("main thread id: %d cond wait start\n", tid);
/* it will block and unlock mutex
to let other thread can get mutex */
pthread_cond_wait(&cond, &mutex);
printf("main thread id: %d cond wait end\n", tid);
}
pthread_mutex_unlock(&mutex);
timer_delete(timer_id);
return 0;
}to reproduce:
- clang -fsanitize=thread -g timer_sample.cc
- ./a.out
results in:
Thread 2 "a.out" received signal SIGSEGV, Segmentation fault.
[Switching to Thread 0x7ffff6b70f00 (LWP 7548)]
0x00005555555fd351 in __sanitizer::CombinedAllocator<__sanitizer::SizeClassAllocator64<__tsan::AP64>, __sanitizer::LargeMmapAllocatorPtrArrayDynamic>::Allocate(__sanitizer::SizeClassAllocator64LocalCache<__sanitizer::SizeClassAllocator64<__tsan::AP64> >*, unsigned long, unsigned long) ()
(gdb) bt
#0 0x00005555555fd351 in __sanitizer::CombinedAllocator<__sanitizer::SizeClassAllocator64<__tsan::AP64>, __sanitizer::LargeMmapAllocatorPtrArrayDynamic>::Allocate(__sanitizer::SizeClassAllocator64LocalCache<__sanitizer::SizeClassAllocator64<__tsan::AP64> >*, unsigned long, unsigned long) ()
#1 0x00005555555fd041 in __tsan::user_alloc_internal(__tsan::ThreadState*, unsigned long, unsigned long, unsigned long, bool) ()
#2 0x00005555555fdba1 in __tsan::user_alloc(__tsan::ThreadState*, unsigned long, unsigned long) ()
#3 0x000055555559fc5d in malloc ()
#4 0x00007ffff7d25b70 in timer_helper_thread (arg=<optimized out>) at ../sysdeps/unix/sysv/linux/timer_routines.c:88
#5 0x00007ffff7d19b43 in start_thread (arg=<optimized out>) at ./nptl/pthread_create.c:442
#6 0x00007ffff7daba00 in clone3 () at ../sysdeps/unix/sysv/linux/x86_64/clone3.S:81Looks like the thread that is spawned will crash upon timer trigger. Any help, greatly appreciated!
Br, Jan
Source: google/sanitizers