waitpid translated the stop and termination signal of a child from the
Linux numbering to the FreeBSD one on every non-Windows host. Darwin
already numbers its signals like FreeBSD, so on macOS the translation
broke them: a child stopped by SIGSTOP (17) was reported as stopped by
20, SIGBUS (10) as 30, SIGSYS (12) as 31, and a child killed by SIGUSR1 (30)
made waitpid report a missing guest equivalent.
macOS now passes the host signal through. The spawn test finds its own
executable with _NSGetExecutablePath on macOS instead of /proc/self/exe,
and also checks a child killed by SIGUSR1, whose number differs between
Linux and FreeBSD and which macOS used to reject.
The macOS write watch handles SIGBUS and SIGSEGV for the whole process.
When a signal is not a write to a watched page and no handler was
installed before it, the handler restored the default action and
returned. That ends the process for a real fault, which runs again and
faults with the default action, but a SIGBUS or SIGSEGV sent with raise
or kill was swallowed: the process kept running. A spawned child that
raised SIGBUS exited with its next exit code instead of dying with the
signal, so guest_posix_spawn failed on macOS.
The handler now raises the signal again after restoring the default
action. It is blocked until the handler returns, so a real fault still
ends with the same signal, and a sent one now does too. An inherited
SIG_IGN keeps the old behaviour.
pthread_setspecific returns an errno value, unlike the Sce function it wraps,
and neither POSIX export had a test. Check the FreeBSD 11.4 results of
_pthread_setspecific and _pthread_getspecific (lib/libthr/thread/thr_spec.c
lines 165-194 and 196-222): a key outside the valid range or a deleted key
makes setspecific return EINVAL (22), getspecific returns NULL for such a key
and for a key never set, a stored value is read back, NULL can be stored, a
new key with a reused number starts empty, and another thread has its own
value.
Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
FreeBSD code reaches its thread pointer through %fs and macOS cannot set
the fs base. The macOS relinker turns each %fs access of a guest image
into a stub that reads the thread pointer from a pthread key and calls
Aps5GuestTlsAllocate on a thread's first access, registers the TLS
descriptor of an image with Aps5GuestTlsRegister, and routes
__tls_get_addr to Aps5GuestTlsGetAddr. No library provided them, so a
relinked executable could not start.
- Aps5GuestTlsRegister validates the descriptor the relinker wrote and
creates the key; its destructor frees the block of a thread.
- Aps5GuestTlsAllocateThreadPointer allocates the block (the TLS template
followed by zeros, then a 0x100-byte thread control block whose first
word points at itself, as on FreeBSD) and stores the thread pointer
under the key.
- Aps5GuestTlsAllocate is the entry the stubs call: rax holds the
descriptor and returns the thread pointer, every other register is
preserved, the upper halves of the ymm registers only where AVX exists.
- Aps5GuestTlsGetAddr returns the block of the thread plus the offset.
Co-authored-by: mugurc <[email protected]>