#247 closed defect (fixed)
libc: feof(pipe_handle) keeps returning 0 after pipe is closed
Reported by: | dmik | Owned by: | bird |
---|---|---|---|
Priority: | normal | Milestone: | libc-0.6.5 |
Component: | libc-backend | Version: | 0.6 |
Severity: | normal | Keywords: | |
Cc: |
Description
Given that stdin of a process is an end of an OS/2 named pipe, the following loop
while (!feof (stdin)) fread (buf, 1, sizeof (buf), stdin);
will not stop when the other end of the pipe is closed.
While one may argue that the loop is incorrect (since besides the EOF there may be e.g. a permanent read error that isn't checked in the loop), the closed pipe is clearly an EOF condition.
On Linux, the above code does stop when the other end of the pipe is closed and there are some programs that rely on that.
Change History (6)
comment:1 by , 13 years ago
comment:2 by , 13 years ago
errno 57 is ENOTCONN. This error is translated in __read() (lib/sys/__read.c) from ERROR_PIPE_NOT_CONNECTED obtained from DosRead().
According to CPREF, ERROR_PIPE_NOT_CONNECTED is returned by DosRead() on the client when the server has called DosDisconnectNPipe() on its end of the pipe. It turns out that if the server bypasses the DosDisconnectNPipe() call and calls DosClose() directly, the error is not reported to the client, the next read operation simply returns 0 bytes (which is equivalent to EOF and fixes both feof() and ferror()). The CPREF is definitely not certain about what is the right behavior...
Anyway, I think that it makes sense to handle ERROR_PIPE_NOT_CONNECTED specially in __read() by simply ignoring it and returning zero (w/o setting errno). This will fix the problem for servers still using a pair of DosDisconnectNPipe() + DosClose() for closing their end of the pipe.
comment:3 by , 13 years ago
Component: | baselayout → libc-backend |
---|---|
Milestone: | → libc-0.6.5 |
Status: | new → accepted |
Summary: | feof(pipe_handle) keeps returning 0 after pipe is closed → libc: feof(pipe_handle) keeps returning 0 after pipe is closed |
Version: | → 0.6 |
comment:4 by , 13 years ago
Status: | accepted → assigned |
---|
comment:5 by , 13 years ago
Resolution: | → fixed |
---|---|
Status: | assigned → closed |
comment:6 by , 13 years ago
Forgot to check the feof() thing, but it turns out it's not only related, it's the same problem. _fill(FILE*) sets _IOEOF when _stream_read, i.e. read, returns 0. :-)
There is one more related problem. On Linux, ferror() for a closed pipe returns 0 while on OS/2 it returns 1. This is also unexpected by many programs (e.g. 7z and rar32 when instructed to compress stdin) that treat this as a fatal error and abort.
In other words, the following program:
being fed a file 22 bytes long on its stdin through a pipe prints this on OS/2:
while this on Linux