Bug 7932 - POSIX conformance error: fscanf(3) + O_NONBLOCK + empty pipe
POSIX conformance error: fscanf(3) + O_NONBLOCK + empty pipe
Status: CLOSED CURRENTRELEASE
Product: Red Hat Linux
Classification: Retired
Component: glibc (Show other bugs)
6.0
All Linux
low Severity low
: ---
: ---
Assigned To: Jakub Jelinek
:
Depends On:
Blocks:
  Show dependency treegraph
 
Reported: 1999-12-21 13:15 EST by Jay Turner
Modified: 2016-11-24 07:25 EST (History)
2 users (show)

See Also:
Fixed In Version:
Doc Type: Bug Fix
Doc Text:
Story Points: ---
Clone Of:
Environment:
Last Closed: 2002-12-13 14:19:04 EST
Type: ---
Regression: ---
Mount Type: ---
Documentation: ---
CRM:
Verified Versions:
Category: ---
oVirt Team: ---
RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: ---


Attachments (Terms of Use)

  None (edit)
Description Glen Foster 1999-12-21 13:15:46 EST
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-04 21:52:59 EST
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 10:18:59 EST
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 11:59:59 EST
reprioritize
Comment 4 Cristian Gafton 2000-05-22 10:52:59 EDT
assign to jakub

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