Skip site navigation (1)Skip section navigation (2)
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-current" 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>