Note: This is a beta release of Red Hat Bugzilla 5.0. The data contained within is a snapshot of the live data so any changes you make will not be reflected in the production Bugzilla. Also email is disabled so feel free to test any aspect of the site that you want. File any problems you find or give feedback here.
Bug 7932 - POSIX conformance error: fscanf(3) + O_NONBLOCK + empty pipe
Summary: POSIX conformance error: fscanf(3) + O_NONBLOCK + empty pipe
Keywords:
Status: CLOSED CURRENTRELEASE
Alias: None
Product: Red Hat Linux
Classification: Retired
Component: glibc
Version: 6.0
Hardware: All
OS: Linux
low
low
Target Milestone: ---
Assignee: Jakub Jelinek
QA Contact:
URL:
Whiteboard:
Depends On:
Blocks:
TreeView+ depends on / blocked
 
Reported: 1999-12-21 18:15 UTC by Jay Turner
Modified: 2016-11-24 12:25 UTC (History)
2 users (show)

Fixed In Version:
Doc Type: Bug Fix
Doc Text:
Clone Of:
Environment:
Last Closed: 2002-12-13 19:19:04 UTC


Attachments (Terms of Use)

Description Glen Foster 1999-12-21 18:15:46 UTC
In the PCTS (POSIX Conformance Test Suite), the fscanf(3) tests fail
on test-case #5 -- reading from a pipe with O_NONBLOCK set.

To reproduce:

	int p[2];
	FILE *fp;
	char buf[64];
/* ... */
	pipe(p);
	flags = fcntl(p[0], F_GETFL);
	fcntl(p[0], F_SETFL, flags | O_NONBLOCK);
	fp = fdopen(p[0], "r");
	fscanf(fp, "%s", inbuf);

... the fscanf(3) is supposed to fail (e.g., return -1) and
set errno to EAGAIN.  Instead, fscanf(3) returns 0 and errno
is not set to anything.  This is a POSIX conformance defect.

POSIX.1 (1996) wording: under read(2), p. 151, lines 157-161

When attempting to read from an empty pipe (or FIFO):

    (1) If no process has the pipe open for writing, read()
        shall return zero to indicate end-of-file.
    (2) If some process has the pipe open for writing and
        O_NONBLOCK is set, read() shall return -1 and set
        errno to EAGAIN.

... let me know if I can clear anything up.

Glen

Comment 1 Cristian Gafton 2000-01-05 02:52:59 UTC
this looks correct to me. Did  any process have the pipe open for writting? If
not, returning 0 is the right thing to do, as the paragraph you quoted states.

Please send complete small testcase and repoen if disagree.

Comment 2 Glen Foster 2000-01-05 15:18:59 UTC
The pipe in the listed code fragment *is* open for writing; it's in p[1],
the write-side of the pipe (it was never closed).  I have included below a
more detailed test-case that proves the point of the original defect filed.

Note that when compiled "as is" *and* when compiled -DREAD_ONLY (to close the
write-side of the pipe before calling scanf()), BOTH cases result in errno
29 (ESPIPE == Illegal seek) from the scanf() call.  This return is acceptable
if the write-side is closed but POSIX clearly states that when the write-side
is open, errno EAGAIN is to be returned when there's (a) no data available
and (b) O_NONBLOCK is set.

Newer test code follows -- let me know if you have any questions.  (Glen)
[snip]
#include <stdio.h>
#include <fcntl.h>
#include <errno.h>

#define STRING  "This is a string"

main()
{
        int flags, val, p[2], len = strlen(STRING);
        FILE *fp;
        char inbuf[64];

        if (pipe(p) < 0) {
                perror("pipe");
                exit(1);
        }
        if ((flags = fcntl(p[0], F_GETFL)) < 0) {
                perror("fcntl(F_GETFL)");
                exit(1);
        }
        if (fcntl(p[0], F_SETFL, flags | O_NONBLOCK) < 0) {
                perror("fcntl(F_SETFL)");
                exit(1);
        }
        if ((fp = fdopen(p[0], "r")) == (FILE *) NULL) {
                perror("fdopen");
                exit(1);
        }
#ifdef  READ_ONLY
        printf("DEBUG: Closing write-side of pipe...\n");
        if (close(p[1]) < 0) {
                perror("close");
                exit(1);
        }
#endif  /* READ_ONLY */
#ifdef  FORCE_FEED
        printf("DEBUG: Forcing data into pipe: \"%s\"\n", STRING);
        if (write(p[1], STRING, len) != len) {
                perror("write");
                exit(1);
        }
#elif   DEBUG_READ
        printf("DEBUG: calling read() instead of fscanf()\n");
        if (read(p[0], inbuf, BUFSIZ) < 0) {
                perror("read");
                if (errno == EAGAIN) {
                        printf("Proper return failure from read()\n");
                        exit(0);
                }
        }
        exit(1);
#endif  /* DEBUG_READ */
        if ((val = fscanf(fp, "%s", inbuf)) == EOF) {
                if (errno != EAGAIN) {
                        perror("fscanf");
                        exit(1);
                }
                printf("errno = EAGAIN (%d), correct ala POSIX\n", errno);
                exit(0);
        }
        fprintf(stderr, "fscanf() returns %d\n", val);
        fprintf(stderr, "fscanf() found data: \"%s\"\n", inbuf);
#ifdef  FORCE_FEED
        exit(0);
#endif  /* FORCE_FEED */
        exit(1);
}

Comment 3 Elliot Lee 2000-02-03 16:59:59 UTC
reprioritize

Comment 4 Cristian Gafton 2000-05-22 14:52:59 UTC
assign to jakub


Note You need to log in before you can comment on or make changes to this bug.