Race condition in timer creation
Originally reported here: https://github.com/isc-projects/bind9/pull/2
A crash happened with the following call trace:
(gdb) thread 4
[Switching to thread 4 (LWP 1827)]
#0 __lll_unlock_wake () at ../sysdeps/unix/sysv/linux/x86_64/lowlevellock.S:371
371 ../sysdeps/unix/sysv/linux/x86_64/lowlevellock.S: No such file or directory.
(gdb) bt
#0 __lll_unlock_wake () at ../sysdeps/unix/sysv/linux/x86_64/lowlevellock.S:371
#1 0x00007f792dfe61f4 in __pthread_mutex_unlock_usercnt (mutex=mutex@entry=0x7f792f045028, decr=decr@entry=1) at pthread_mutex_unlock.c:55
#2 0x00007f792dfe62aa in __GI___pthread_mutex_unlock (mutex=mutex@entry=0x7f792f045028) at pthread_mutex_unlock.c:324
#3 0x00007f792e234f3e in isc__timer_create (manager0=0x7f792f045010, type=, expires=, interval=, task=,
action=, arg=0x55a04c063a50, timerp=0x55a04c063a88) at ../../../bind-9.10.3-P3/lib/isc/timer.c:485
#4 0x000055a04ac16610 in add_timeout (when=0x7ffea6082f90, where=0x7ffea6082fa0, what=0x0, ref=0xffffffff, unref=0x7f792f045028) at ../../dhcp-4.3.4/common/dispatch.c:354
#5 0x000055a04ac01cf1 in send_discover (cpp=0x55a04c063db0) at ../../dhcp-4.3.4/client/dhclient.c:2315
#6 0x000055a04abf8ac8 in main (argc=, argv=) at ../../dhcp-4.3.4/client/dhclient.c:795
(gdb) thread 1
[Switching to thread 1 (LWP 1828)]
#0 __GI_raise (sig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:58
58 ../sysdeps/unix/sysv/linux/raise.c: No such file or directory.
(gdb) bt
#0 __GI_raise (sig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:58
#1 0x00007f792dc713fa in __GI_abort () at abort.c:89
#2 0x00007f792e20c7af in isc_assertion_failed (file=file@entry=0x7f792e252b60 "../../../bind-9.10.3-P3/lib/isc/timer.c", line=line@entry=1163,
type=type@entry=isc_assertiontype_require,
cond=cond@entry=0x7f792e2531f0 "timerp != ((void *)0) && ((*timerp) != ((void *)0) && (*timerp)->magic == (('A') << 24 | ('t') << 16 | ('m') << 8 | ('r')))")
at ../../../bind-9.10.3-P3/lib/isc/assertions.c:59
#3 0x00007f792e2358c1 in isc_timer_detach (timerp=timerp@entry=0x55a04c063a88) at ../../../bind-9.10.3-P3/lib/isc/timer.c:1163
#4 0x000055a04ac1625b in isclib_timer_callback (taskp=, eventp=0x7f792f04e130) at ../../dhcp-4.3.4/common/dispatch.c:179
#5 0x00007f792e22f64c in dispatch (manager=0x7f792f042010) at ../../../bind-9.10.3-P3/lib/isc/task.c:1130
#6 run (uap=0x7f792f042010) at ../../../bind-9.10.3-P3/lib/isc/task.c:1302
#7 0x00007f792dfe2464 in start_thread (arg=0x7f792d1d3700) at pthread_create.c:456
#8 0x00007f792dd24cef in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:105
(gdb) print *(struct isc_timer **) 0x55a04c063a88
$15 = (struct isc_timer *) 0x0
The race condition is the timer elapses before isc__timer_create() returns the pointer to the caller. Assigning the return pointer before enabling the timer will fix it.