A socket EVFILT_READ knote whose NOTE_LOWAT mark is below 1 is now always ready and reports the bytes in the receive buffer, 0 when it is empty, because FreeBSD 11.4 filt_soread returns kn_data >= kn_sdata and the bytes available are never negative. This holds for level-triggered and EV_CLEAR knotes and when EV_ADD changes the mark of an existing knote. A listening socket ignores the mark, as filt_solisten does. An EVFILT_WRITE mark below 1 still throws.
Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
Keep both EVFILT_PROC (main) and EVFILT_SIGNAL (this PR) in Kqueue.cpp: the constants, the two knote functions, the filter check and the dispatch. Debt doc: main's EVFILT_PROC and pipe wording with the PR's signal text.
The EVFILT_VNODE host watch thread in AddVnodeEvent ran RunHostWatch
directly. RunHostWatch throws std::runtime_error on poll, inotify, kqueue
or change-notification failures, and an exception escaping a detached
std::thread calls std::terminate and aborts the whole process. The thread
entry now catches std::exception, reports the message on stderr and ends
the watch, which RunHostWatch has already closed on every throw path.
An EV_ADD of EVFILT_FS is now accepted instead of throwing, as FreeBSD 11.4 filt_fsattach accepts it: the knote gets EV_CLEAR, and fflags and data start at 0. It never fires, as nothing here signals a filesystem event. EV_ENABLE, EV_DISABLE and EV_DELETE act on the knote as on other knotes.
An EV_ADD of EVFILT_SIGNAL is now accepted instead of throwing, as FreeBSD 11.4 filt_sigattach accepts it: the knote gets EV_CLEAR, and data counts the signals with that number sent since the knote was last reported, ignored ones included, as tdsendsignal counts them before its ignore check. Signals sent by raise, kill, killpg and pthread_kill and the ITIMER_REAL expiry are counted. EV_ENABLE, EV_DISABLE and EV_DELETE act on the knote as on other knotes.
Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
An EV_ADD of EVFILT_PROC on the calling process with NOTE_EXIT or no notes is now accepted instead of throwing, as FreeBSD 11.4 filt_procattach accepts it: the knote gets EV_CLEAR and does not fire while the process runs, and EV_ADD, EV_ENABLE, EV_DISABLE, EV_DELETE and EV_FORCEONESHOT then act on it as on other knotes. EVFILT_PROC on another process or with notes other than NOTE_EXIT still throws.
Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
Emscripten targets wasm64 without x86 assembly, Linux-only headers or the
x87 long double. These changes add __EMSCRIPTEN__ paths beside the host
ones; native builds compile the same code as before.
- libc: long doubles in guest varargs and scanf go through
GuestLongDouble, a plain copy where long double is the x87 format;
APS5_EXPORT emits no assembler alias; the guest arena is one aligned
allocation that zeroes pages when they are committed again; getifaddrs
keeps its link-level entries on Linux; /proc lookups and the host
stderr duplicate are left out.
- libkernel: file-backed mmap, EVFILT_VNODE watches, getcontext and
setcontext throw; getdents replaces the raw getdents64 syscall;
getdtablesize takes the resource limit alone.
- VideoOut leaves SDL, the display window and the HDR probe out,
Sysmodule asks libkernel for unwind information and Net includes
sys/time.h.
The staging buffer was sized by the guest's nevents, so a request for
INT_MAX events allocated about 64 GiB before the queue reported how many
were pending. It's now bounded at 1024 events; kevent may return fewer
than requested, and events left in the queue come back on the next call.
The test covers an INT_MAX request and a 1030-event queue, and moves away
from the end of StandardInput and the start of main, where #9575 and
#10014 also add tests.
kevent read the changelist and the timeout and wrote the eventlist in
place, so a non-null pointer into unmapped or read-only memory crashed
the host. It now copies the timeout in first, as FreeBSD's sys_kevent
does, copies each change in with GuestCopyIn_nid_no_patch and copies
EV_ERROR entries out one at a time. Triggered events are collected by
the same single queue call as before into a host buffer (on the stack
up to 64 events) and copied out with GuestCopyOut_nid_no_patch, so
level-triggered events are still reported once per call. Any failed
copy returns EFAULT.
A cleared kqueue watch read the watched queue's triggered count and its
activation counter under two separate locks, so an activation between the
reads was marked seen without making the watch active, and the wakeup was
lost. SnapshotTriggered now returns both under one lock. Every poll of an
active watch also rechecks the count, as kqueue_scan reruns filt_kqueue:
it drops when the watched queue empties and reports the current count.
EV_ADD and EV_ENABLE of an existing watch re-arm it. A separate
guest_kqueue_cleared_race test triggers the watched queue from another
thread while the watching queue waits.
FreeBSD re-evaluates a kqueue's EVFILT_READ note from kqueue_wakeup,
which runs whenever the watched kqueue queues a note, so an EV_CLEAR
note fires again only after such an activation. The equeue now counts
activations, and the EV_CLEAR note fires when the count moves while
notes are queued.
TakeSnapshot read FileBasicInfo and then FileStandardInfo. A truncate or
write landing between the two left a snapshot with the new size and the
old LastWriteTime, and the next poll reported the same size with a newer
LastWriteTime as NOTE_WRITE. guest_kqueue's FileWatch aborts on Windows
when that happens after its ftruncate to 0.
Read FileBasicInfo again after FileStandardInfo and retry until both
reads agree. The window NTFS itself leaves, a truncate's new
LastWriteTime shown before its new size, stays and is listed in the
libkernel debt.
MeasureFiles registered the descriptors it measures in m_measuring and removed them only on the normal path, so an exception between unlocking and relocking left them there and every later RemoveDescriptorEvents for one of them waited forever. Both vectors are reserved before anything is registered, and a guard owns the registration: on every exit it relocks if needed, removes the entries and notifies.
On PS5 firmware 13.60 sceKernelGetEventError returns 0x80020000 plus the
event's fflags in 32 bits for every non-zero fflags, including values
above 0xFFFF, where it used to throw.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
- a timer change with EV_ADD unset and data 0 keeps the period; one that set
fflags was silently ignored, where FreeBSD 11's kqueue_register copies it
onto the note: it now throws with the other re-adds, waiting for the
measured rules
- EV_ENABLE on a disabled timer reports the expiries missed while disabled in
one step and keeps the note's phase, as FreeBSD 11's filt_timerexpire counts
a disabled note and keeps its p_nexttime; TimerDisableEnableRearm pins it
(5 serial runs and 3 rounds of 8 parallel copies pass)
- the next-wait abort from the review round was observed before main's
5cbc46029b wait refactor and does not reproduce