this repo has no description
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Add a linux_futex syscall that doesn't modify errno

This fixes some crashes due to accessing errno (which is per-thread)
after the thread had already been terminated. This was due to us having
to unguard an FD when a thread dies, which requires us to take a lock.

+14 -8
+5
src/kernel/emulation/linux/ext/futex.c
··· 21 21 return rv; 22 22 } 23 23 24 + VISIBLE 25 + int __linux_futex_reterr(int *uaddr, int op, int val, const struct timespec *timeout, int *uaddr2, int val3) { 26 + int rv = LINUX_SYSCALL(__NR_futex, uaddr, op, val, timeout, uaddr2, val3); 27 + return (rv < 0) ? errno_linux_to_bsd(rv) : rv; 28 + };
+1
src/kernel/emulation/linux/ext/futex.h
··· 8 8 9 9 int __linux_futex (int *uaddr, int op, int val, const struct timespec *timeout, 10 10 int *uaddr2, int val3); 11 + int __linux_futex_reterr(int *uaddr, int op, int val, const struct timespec *timeout, int *uaddr2, int val3); 11 12 12 13 #endif 13 14
+4 -4
src/libsimple/src/lock.c
··· 31 31 #include <sys/syscall.h> 32 32 #include <unistd.h> 33 33 #elif LIBSIMPLE_DARLING 34 - extern int __linux_futex(int* uaddr, int op, int val, const struct timespec* timeout, int* uaddr2, int val3); 34 + extern int __linux_futex_reterr(int* uaddr, int op, int val, const struct timespec* timeout, int* uaddr2, int val3); 35 35 #endif 36 36 37 37 #if LIBSIMPLE_DARLING 38 - #define linux_futex __linux_futex 38 + #define linux_futex __linux_futex_reterr 39 39 #else // !LIBSIMPLE_DARLING 40 - static int linux_futex(int* uaddr, int op, int val, const struct timespec* timeout, int* uaddr2, int val3) { 40 + static void linux_futex(int* uaddr, int op, int val, const struct timespec* timeout, int* uaddr2, int val3) { 41 41 #if LIBSIMPLE_LINUX 42 - return syscall(SYS_futex, uaddr, op, val, timeout, uaddr2, val3); 42 + syscall(SYS_futex, uaddr, op, val, timeout, uaddr2, val3); 43 43 #else 44 44 #error linux_futex not implemented for this platform 45 45 #endif
+4 -4
src/xtrace/lock.c
··· 70 70 xtrace_lock_debug("going to wait"); 71 71 // do the actual sleeping 72 72 // we expect `xtrace_lock_state_locked_contended` because we don't want to sleep if it's not contended 73 - __linux_futex(&lock->state, FUTEX_WAIT, xtrace_lock_state_locked_contended, NULL, 0, 0); 73 + __linux_futex_reterr(&lock->state, FUTEX_WAIT, xtrace_lock_state_locked_contended, NULL, 0, 0); 74 74 xtrace_lock_debug("awoken"); 75 75 } 76 76 ··· 95 95 // if it was previously contended, then we need to wake someone up 96 96 if (prev == xtrace_lock_state_locked_contended) { 97 97 xtrace_lock_debug("waking someone up"); 98 - __linux_futex(&lock->state, FUTEX_WAKE, 1, NULL, 0, 0); 98 + __linux_futex_reterr(&lock->state, FUTEX_WAKE, 1, NULL, 0, 0); 99 99 } 100 100 }; 101 101 ··· 152 152 case xtrace_once_state_triggered_contended: { 153 153 xtrace_once_debug("waking up all waiters..."); 154 154 // otherwise, we have to wake someone up 155 - __linux_futex(&once->state, FUTEX_WAKE, INT_MAX, NULL, 0, 0); 155 + __linux_futex_reterr(&once->state, FUTEX_WAKE, INT_MAX, NULL, 0, 0); 156 156 } break; 157 157 } 158 158 ··· 184 184 // somebody is already performing the callback and there are already waiters; 185 185 // let's wait 186 186 xtrace_once_debug("someone is already performing the callback with waiters; going to wait..."); 187 - __linux_futex(&once->state, FUTEX_WAIT, prev, NULL, 0, 0); 187 + __linux_futex_reterr(&once->state, FUTEX_WAIT, prev, NULL, 0, 0); 188 188 189 189 xtrace_once_debug("woken up"); 190 190