The example code used for kqueue (2) is a bit wrong. Checking event.flags is not needed. What is expected? Remove event.flags check like this: @@ -655,8 +655,6 @@ ret = kevent(kq, &event, 1, NULL, 0, NULL); if (ret == -1) err(EXIT_FAILURE, "kevent register"); - if (event.flags & EV_ERROR) - errx(EXIT_FAILURE, "Event error: %s", strerror(event.data)); for (;;) { /* Sleep until something happens. */ Why it is expected? If I understand the manual correctly, if |nevents| argument is 0, -1 would be returned for error, and it won't modify |changelist| argument. In the above example, event. > The kevent() system call returns the number of events placed in the > eventlist, up to the value given by nevents. If an error occurs while > processing an element of the changelist and there is enough room in the > eventlist, then the event will be placed in the eventlist with EV_ERROR > set in flags and the system error in data. Otherwise, -1 will be > returned, and errno will be set to indicate the error condition. If the > time limit expires, then kevent() returns 0. However, the above code expect the kernel to update |event|. Also, a caller should not usually expect the callee updates const value. I believe the following code explains my understanding is correct: https://svnweb.freebsd.org/base/head/sys/kern/kern_event.c?revision=350421&view=markup#l1235 i.e. if |nevents| is 0, registration failure should be notified via return value instead of |changelist| parameter. Note that this issue was not originally found by myself, but suggested by the person who is not familiar with filing a FreeBSD issue. I confirmed the suggestion correct by investigating the kernel before filing the issue. Also, note that NetBSD and OpenBSD use different example code and not affected by this issue.
It looks to me as though the sample code was fixed. /* Initialize kevent structure. */ EV_SET(&event, fd, EVFILT_VNODE, EV_ADD | EV_CLEAR, NOTE_WRITE, 0, NULL); /* Attach event to the kqueue. */ ret = kevent(kq, &event, 1, NULL, 0, NULL); if (ret == -1) err(EXIT_FAILURE, "kevent register"); for (;;) { /* Sleep until something happens. */ Those two lines are now gone. @linimon I think this can be closed.
^Triage: apparently OBE.