Hi, I think, kevent() has a bug. I tested sample programs by attached sources. This sample tests about EVFILT_SIGNAL. I build sample programs by the following commands. % gcc -O2 -o child child.c % gcc -O2 -o parent parent.c The expected result is the following. % ./parent 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 OK 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 OK But, sometimes the result was the following. % ./parent 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 This result means the number of times the signal has occured was incorrect. In case of EVFILT_SIGNAL, according to `man kevent', `data' retuns the number of times the signal has occurred since the last call to kevent(). This `data' is recorded by filt_signal() (This is f_event in struct filterops). The system call kevent()'s events are processed by kqueue_scan() in kern_event.c. In kqueue_scan(), kn->kn_fop->f_event() is allways called after KN_INFLUX is set to kn->kn_status. On the other hand, kernel events are occured by knote() in kern_event.c. (In EVFILT_SIGNAL, knote() is called from tdsendsignal() in kern_sig.c.) In knote(), kn->kn_fop->f_event() is called only when KN_INFLUX is not set in kn->kn_status. In race condition between kqueue_scan() and knote(), kn->kn_fop->f_event() from knote() may not be called, I think. In knote(), because the context holds knlist's lock, the context can not sleep. So, KN_INFLUX should not be set on calling kn->kn_fop->f_event() in kqueue_scan(), I think. What do you think about this issue? Best regards, Kohji Okuno #include <sys/types.h> #include <stdlib.h> #include <unistd.h> #include <stdio.h> int main() { sleep(1); exit(0); } #include <sys/types.h> #include <sys/wait.h> #include <sys/event.h> #include <sys/time.h> #include <stdlib.h> #include <stdio.h> #include <unistd.h> #include <signal.h> #define NUM_CHILDREN 20 int main() { int i; pid_t pid; char *argv[2] = {"child", NULL}; struct kevent kev; int kqfd = kqueue(); int count; int err; int status; EV_SET(&kev, SIGCHLD, EVFILT_SIGNAL, EV_ADD, 0, 0, 0); kevent(kqfd, &kev, 1, NULL, 0, NULL); while (1) { count = 0; for (i = 0; i < NUM_CHILDREN; i++) { pid = fork(); if (pid == 0) { execve("./child", argv, NULL); } } while (1) { err = kevent(kqfd, NULL, 0, &kev, 1, NULL); if (err > 0 && kev.ident == SIGCHLD) { for (i = 0; i < kev.data; i++) { pid = waitpid(-1, &status, WNOHANG); if (pid > 0) { count++; printf("%d ", count); fflush(stdout); if (count == NUM_CHILDREN) { printf("\nOK\n"); goto next; } } } } } next: ; } exit(0); }Received on Wed Apr 02 2014 - 00:45:40 UTC
This archive was generated by hypermail 2.4.0 : Wed May 19 2021 - 11:40:48 UTC