POSIX leaves using a semaphore after sem_destroy undefined, and EINVAL
there rested only on FreeBSD's libc source, not on a console result.
Keep the future-deadline checks, which POSIX defines.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
GuestPosixSem timed out sem_timedwait only on an expired deadline and
never used a semaphore after sem_destroy. CheckFutureDeadline requires a
realtime deadline 50 ms ahead to fail with ETIMEDOUT after at least
40 ms without changing the count, and a post before a 5 s deadline to
release the waiter with 0. CheckDestroyed requires sem_wait, sem_trywait,
sem_timedwait, sem_post, sem_getvalue and a second sem_destroy on a
destroyed semaphore to fail with EINVAL, as FreeBSD's libc does once
sem_destroy has cleared the semaphore.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Keep a copy of the name with the semaphore and move the export from the libkernel_sys stub into libkernel next to the other sem_* exports.
Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
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]>