From owner-freebsd-current@FreeBSD.ORG Wed Apr 2 02:45:40 2014 Return-Path: Delivered-To: freebsd-current@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [8.8.178.115]) (using TLSv1 with cipher ADH-AES256-SHA (256/256 bits)) (No client certificate requested) by hub.freebsd.org (Postfix) with ESMTPS id 63B70364 for ; Wed, 2 Apr 2014 02:45:40 +0000 (UTC) Received: from smtp.mei.co.jp (smtp.mei.co.jp [133.183.100.20]) by mx1.freebsd.org (Postfix) with ESMTP id 1A5D3B65 for ; Wed, 2 Apr 2014 02:45:39 +0000 (UTC) Received: from mail-gw.jp.panasonic.com ([157.8.1.157]) by smtp.mei.co.jp (8.12.11.20060614/3.7W/kc-maile11) with ESMTP id s322jbjW010762 for ; Wed, 2 Apr 2014 11:45:37 +0900 (JST) Received: from epochmail.jp.panasonic.com ([157.8.1.130]) by mail.jp.panasonic.com (8.11.6p2/3.7W/kc-maili17) with ESMTP id s322jb318122 for ; Wed, 2 Apr 2014 11:45:37 +0900 Received: by epochmail.jp.panasonic.com (8.12.11.20060308/3.7W/lomi11) id s322jb9X027382; Wed, 2 Apr 2014 11:45:37 +0900 Received: from localhost by lomi11.jp.panasonic.com (8.12.11.20060308/3.7W) with ESMTP id s322jbM6027343; Wed, 2 Apr 2014 11:45:37 +0900 Date: Wed, 02 Apr 2014 11:45:16 +0900 (JST) Message-Id: <20140402.114516.1300054841784626892.okuno.kohji@jp.panasonic.com> To: freebsd-current@freebsd.org Subject: kevent has bug? From: Kohji Okuno Organization: Panasonic Corporation X-Mailer: Mew version 6.5 on Emacs 24.3 / Mule 6.0 (HANACHIRUSATO) Mime-Version: 1.0 Content-Type: Multipart/Mixed; boundary="--Next_Part(Wed_Apr__2_11_45_16_2014_492)--" Content-Transfer-Encoding: 7bit Cc: okuno.kohji@jp.panasonic.com X-BeenThere: freebsd-current@freebsd.org X-Mailman-Version: 2.1.17 Precedence: list List-Id: Discussions about the use of FreeBSD-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 02 Apr 2014 02:45:40 -0000 ----Next_Part(Wed_Apr__2_11_45_16_2014_492)-- Content-Type: Text/Plain; charset=us-ascii Content-Transfer-Encoding: 7bit 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 ----Next_Part(Wed_Apr__2_11_45_16_2014_492)-- Content-Type: Text/Plain; charset=us-ascii Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename="child.c" #include #include #include #include int main() { sleep(1); exit(0); } ----Next_Part(Wed_Apr__2_11_45_16_2014_492)-- Content-Type: Text/Plain; charset=us-ascii Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename="parent.c" #include #include #include #include #include #include #include #include #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); } ----Next_Part(Wed_Apr__2_11_45_16_2014_492)----