From owner-freebsd-bugs@FreeBSD.ORG Tue Mar 21 10:00:31 2006 Return-Path: X-Original-To: freebsd-bugs@hub.freebsd.org Delivered-To: freebsd-bugs@hub.freebsd.org Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id 54A0A16A428 for ; Tue, 21 Mar 2006 10:00:31 +0000 (UTC) (envelope-from gnats@FreeBSD.org) Received: from freefall.freebsd.org (freefall.freebsd.org [216.136.204.21]) by mx1.FreeBSD.org (Postfix) with ESMTP id AC3B643D53 for ; Tue, 21 Mar 2006 10:00:30 +0000 (GMT) (envelope-from gnats@FreeBSD.org) Received: from freefall.freebsd.org (gnats@localhost [127.0.0.1]) by freefall.freebsd.org (8.13.4/8.13.4) with ESMTP id k2LA0UuT086419 for ; Tue, 21 Mar 2006 10:00:30 GMT (envelope-from gnats@freefall.freebsd.org) Received: (from gnats@localhost) by freefall.freebsd.org (8.13.4/8.13.4/Submit) id k2LA0U6h086418; Tue, 21 Mar 2006 10:00:30 GMT (envelope-from gnats) Resent-Date: Tue, 21 Mar 2006 10:00:30 GMT Resent-Message-Id: <200603211000.k2LA0U6h086418@freefall.freebsd.org> Resent-From: FreeBSD-gnats-submit@FreeBSD.org (GNATS Filer) Resent-To: freebsd-bugs@FreeBSD.org Resent-Reply-To: FreeBSD-gnats-submit@FreeBSD.org, Oliver Fromme Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id 1457416A400 for ; Tue, 21 Mar 2006 09:56:57 +0000 (UTC) (envelope-from olli@lurza.secnetix.de) Received: from lurza.secnetix.de (lurza.secnetix.de [83.120.8.8]) by mx1.FreeBSD.org (Postfix) with ESMTP id 77C1943D49 for ; Tue, 21 Mar 2006 09:56:56 +0000 (GMT) (envelope-from olli@lurza.secnetix.de) Received: from lurza.secnetix.de (ncvkbc@localhost [127.0.0.1]) by lurza.secnetix.de (8.13.4/8.13.4) with ESMTP id k2L9untZ094655; Tue, 21 Mar 2006 10:56:54 +0100 (CET) (envelope-from oliver.fromme@secnetix.de) Received: (from olli@localhost) by lurza.secnetix.de (8.13.4/8.13.1/Submit) id k2L9ungW094654; Tue, 21 Mar 2006 10:56:49 +0100 (CET) (envelope-from olli) Message-Id: <200603210956.k2L9ungW094654@lurza.secnetix.de> Date: Tue, 21 Mar 2006 10:56:49 +0100 (CET) From: Oliver Fromme To: FreeBSD-gnats-submit@FreeBSD.org X-Send-Pr-Version: 3.113 Cc: Oliver Fromme Subject: kern/94772: FIFOs (named pipes) + select() == broken X-BeenThere: freebsd-bugs@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list Reply-To: Oliver Fromme List-Id: Bug reports List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 21 Mar 2006 10:00:31 -0000 >Number: 94772 >Category: kern >Synopsis: FIFOs (named pipes) + select() == broken >Confidential: no >Severity: serious >Priority: medium >Responsible: freebsd-bugs >State: open >Quarter: >Keywords: >Date-Required: >Class: sw-bug >Submitter-Id: current-users >Arrival-Date: Tue Mar 21 10:00:29 GMT 2006 >Closed-Date: >Last-Modified: >Originator: Oliver Fromme >Release: FreeBSD 6.1-PRERELEASE i386 >Organization: secnetix GmbH & Co. KG http://www.secnetix.de/bsd >Environment: System: FreeBSD epia.fromme.com 6.1-PRERELEASE FreeBSD 6.1-PRERELEASE #0: Tue Mar 21 10:21:23 CET 2006 olli@epia.fromme.com:/usr/src/sys/i386/compile/EPIA i386 I'm using the latest RELENG_6 from today (March 21, 2006). >Description: I recently wondered why several of my scripts that use a named pipe (FIFO) don't work on FreeBSD. After some debugging it turned out that select() seems to be broken when used with FIFOs on FreeBSD 6. Particularly, this is the bug I'm suffering from: When a FIFO had been opened for reading and the writing process closes it, the reading process blocks in select(), even though the descriptor is ready for read(). If the select() call is omitted, read() returns 0 immediately indicating EOF. But as soon as you use select(), it blocks and there is no chance to detect the EOF condition. That's clearly a serious violation of POSIX, SUSv3, Stevens APUE and all other documentations about select() and named pipes that I'm aware of. It needs to be fixed. >How-To-Repeat: Please see the small test program below. Compile it like this: cc -O -o fifotest fifotest.c Then create a named pipe, e.g.: $ mkfifo fifo And run the test program: ./fifotest fifo It will block on the open(), which is to be expected (correct behaviour so far). Then open another shell (e.g. second terminal window) and type: echo foo > fifo You will see from the output of the fifotest program that the open() succeeds, the select() returns 1, and the read() returns 4 bytes ("foo\n"). But then the next call to select() blocks, even though there is an EOF condition! The same test program (with "err()" replaced by a small self-made function) runs without error on all other UNIX systems that I've tried: Linux 2.4.32, Solaris 10, and DEC UNIX 4.0 (predecessor of Tru64). By the way, it's even sufficient to do "cat /dev/null > fifo", i.e. not writing anything at all, but issuing EOF immediately. Under FreeBSD, nothing happens at all in that case. All other UNIX systems recognize EOF (select() returns). The source contains a #define WITH_SELECT. When you undefine it, select() won't be called, only read(). Then the program runs fine and detects the EOF condition correctly. Here's the source code. In case it is mangled somehow by send-pr, I've put a copy on this web page: http://www.secnetix.de/~olli/tmp/fifotest.c #include #include #include #include #include #include #include #define WITH_SELECT int main (int argc, char *argv[]) { int fd_in, result; char buffer[4096]; if (argc != 2) errx (1, "Usage: %s \n", argv[0]); fprintf (stderr, "Opening FIFO for reading (might block) ...\n"); if ((fd_in = open(argv[1], O_RDONLY, 0666)) < 0) err (1, argv[1]); fprintf (stderr, "FIFO opened successfully.\n"); for (;;) { #ifdef WITH_SELECT fd_set fds_r; FD_ZERO (&fds_r); FD_SET (fd_in, &fds_r); fprintf (stderr, "Calling select(read FD %d) ...\n", fd_in); if ((result = select(fd_in + 1, &fds_r, NULL, NULL, NULL)) < 0) err (1, "select()"); fprintf (stderr, "... return value is %d.\n", result); if (! FD_ISSET(fd_in, &fds_r)) continue; #endif result = read(fd_in, buffer, 4096); fprintf (stderr, "read() returned %d bytes.\n", result); if (result < 1) { if (result < 0) err (1, "read()"); break; } } fprintf (stderr, "Got EOF!\n"); close (fd_in); return 0; } /* END OF SOURCE */ >Fix: None, known, unfortunately. :-( >Release-Note: >Audit-Trail: >Unformatted: