sem_post raised the count under the semaphore's lock, released the
lock, and only then called NotifyOne on the heap PosixSemaphore. A
thread that took the count in that gap could call sem_destroy, which
deletes the object, and the poster then ran NotifyOne on freed memory.
FreeBSD 11.4's sem_post touches only the caller's sem_t after it
publishes the token, and its sem_destroy only clears _magic, so a
thread may destroy the semaphore as soon as its wait returns.
Call NotifyOne before the lock is released. A thread takes the count
only under that lock, so the unlock is the poster's last access.
guest_posix_sem_post now runs 20000 rounds that post to a semaphore
the main thread destroys once sem_trywait gets the count; with the old
order the poster crashes in NotifyOne.
Co-Authored-By: Claude Opus 5.5 <[email protected]>