| 1 | @[has_globals] |
| 2 | module os |
| 3 | |
| 4 | // g_v_os_execute_mutex_storage backs a pthread_mutex_t used to serialize |
| 5 | // pipe()+spawn from os.execute(). On macOS arm64 GitHub Actions runners, |
| 6 | // two threads racing through pipe()+posix_spawn produced empty captured |
| 7 | // output even with FD_CLOEXEC on the pipe ends. 128 bytes is comfortably |
| 8 | // larger than sizeof(pthread_mutex_t) on macOS (64) and Linux (40-48), |
| 9 | // so we never need to know the actual layout — only the C functions |
| 10 | // declared in builtin/cfns.c.v which take voidptr. |
| 11 | __global g_v_os_execute_mutex_storage = [128]u8{} |
| 12 | |
| 13 | fn v_os_execute_mutex_ptr() voidptr { |
| 14 | return unsafe { voidptr(&g_v_os_execute_mutex_storage[0]) } |
| 15 | } |
| 16 | |
| 17 | fn init() { |
| 18 | C.pthread_mutex_init(v_os_execute_mutex_ptr(), unsafe { nil }) |
| 19 | } |
| 20 | |
| 21 | fn v_os_execute_lock() { |
| 22 | C.pthread_mutex_lock(v_os_execute_mutex_ptr()) |
| 23 | } |
| 24 | |
| 25 | fn v_os_execute_unlock() { |
| 26 | C.pthread_mutex_unlock(v_os_execute_mutex_ptr()) |
| 27 | } |
| 28 | |