On Fri, Mar 7, 2025 at 1:52 PM Thomas Munro <thomas.munro@gmail.com> wrote:
> I believe I know exactly why: kqueues are considered readable (by
> poll/select/other kqueues) if there are any events queued[1]. Apple's
> EVFILT_TIMER implementation is doing that trick[2] where it leaves
> them queued, but filt_timerprocess() filters them out if its own
> private _FIRED flag isn't set, so kevent() itself won't wake up or
> return them. That trick doesn't survive nesting. I think I would
> call that a bug.
Bleh. Thank you for the analysis!
> Maybe just do the delete-and-add in one call?
>
> EV_SET(&ev[0], 1, EVFILT_TIMER, EV_DELETE, 0, 0, 0);
> EV_SET(&ev[1], 1, EVFILT_TIMER, EV_ADD | EV_ONESHOT, 0, timeout, 0);
> if (kevent(kq, &ev[0], 2, NULL, 0, NULL) < 0)
I think that requires me to copy the EV_RECEIPT handling from
register_socket(), to make sure an ENOENT is correctly ignored on
delete but doesn't mask failures from the addition. Do you prefer that
to the separate calls? (Or, better yet, is it easier than I'm making
it?)
Thanks!
--Jacob