Date: Mon, 12 Nov 2001 15:28:15 +0200 (EET) From: Maxim Sobolev <sobomax@FreeBSD.org> To: jlemon@FreeBSD.org Cc: current@FreeBSD.org, hackers@FreeBSD.org Subject: kqueue(2) doesn't deliver EV_EOF on pipes [patch] Message-ID: <200111121328.fACDSGt04364@vega.vega.com>
next in thread | raw e-mail | index | archive | help
--%--multipart-mixed-boundary-1.4281.1005571695--% Content-Type: text/plain; charset=us-ascii Content-Transfer-Encoding: 7bit Hi, I've noticed that kqueue(2) doesn't notify reader about EV_EOF condition on pipe. Attached simple test program highlights the problem (confirmed both on 5-CURRENT and 4-STABLE). Also attached is the simple fix. -Maxim --%--multipart-mixed-boundary-1.4281.1005571695--% Content-Type: text/plain; charset=us-ascii Content-Transfer-Encoding: 7bit Content-Description: ASCII C program text Content-Disposition: attachment; filename="sys_pipe.c.diff" Index: sys/kern/sys_pipe.c =================================================================== RCS file: /home/ncvs/src/sys/kern/sys_pipe.c,v retrieving revision 1.86 diff -d -u -r1.86 sys_pipe.c --- sys/kern/sys_pipe.c 2001/09/21 22:46:53 1.86 +++ sys/kern/sys_pipe.c 2001/11/12 13:28:05 @@ -1221,6 +1221,7 @@ ppipe->pipe_state |= PIPE_EOF; wakeup(ppipe); + KNOTE(&ppipe->pipe_sel.si_note, 0); ppipe->pipe_peer = NULL; } /* --%--multipart-mixed-boundary-1.4281.1005571695--% Content-Type: text/plain; charset=us-ascii Content-Transfer-Encoding: 7bit Content-Description: ASCII C program text Content-Disposition: attachment; filename="testpipe.c" #include <sys/types.h> #include <sys/event.h> #include <sys/time.h> #include <err.h> #include <signal.h> #include <stdio.h> #include <unistd.h> void testpassed(int sig) { printf("Test passed\n"); exit(0); } int main(int argc, char **argv) { int kq, pid, ppid, nevents; struct kevent changelist[1]; struct kevent eventlist[1]; int pp[2]; pipe(pp); ppid = getpid(); pid = fork(); switch (pid) { case -1: /* Error */ err(1, "can't fork()"); /* NOTREACHED */ case 0: /* Child */ close(pp[1]); kq = kqueue(); EV_SET(changelist, pp[0], EVFILT_READ, EV_ADD | EV_ENABLE | EV_EOF, \ 0, 0, NULL); kevent(kq, changelist, 1, NULL, 0, NULL); for (;;) { nevents = kevent(kq, NULL, 0, eventlist, 1, NULL); if (nevents > 0 || (eventlist[0].flags & EV_EOF) != 0) { kill(ppid, SIGTERM); exit(0); } } break; default: /* Sever */ close(pp[0]); break; } signal(SIGTERM, testpassed); /* Give child some time to initialise kqueue(2) */ sleep(1); close(pp[1]); /* Give child some time to receive EV_EOF and kill us */ sleep(1); kill(pid, SIGTERM); printf("Test failed\n"); exit(1); } --%--multipart-mixed-boundary-1.4281.1005571695--%-- To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-hackers" in the body of the message
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200111121328.fACDSGt04364>