Question about read() behavior and EINTR
Chris Jaeger
cjaeger at ensim.com
Tue Oct 9 18:08:36 EDT 2001
Hi all,
I've encountered an annoying behavior with respect to
the built-in read() function and I'm wondering whether it is
a Python bug, a glibc bug, or a case of abusing read(). For
reference, I'm using Python 2.1.1 on a glibc-2.2.2 Linux
system, with kernel 2.4.2.
I have a python extension module written in C that
executes commands via execl, and returns the stdin, stdout,
and stderr as Python file objects. With one particular
command sequence, my code received an IOError exception
with errno set to 0. I started digging down, and this is
what I've reconstructed about the sequence of events:
- from python:
data = stdout.read(16384)
while data:
<do something with data>
data = stdout.read(16384)
Three read()s occur, with the following behavior:
stdout.read(16384) returns 12288 bytes
stdout.read(16384) returns 1266 bytes
stdout.read(16384) throws IOError(0, 'Error')
I added some tracing code into the python binary and
noticed that the error bit in the FILE structure is set
during the first read, and this is what eventually causes
the IOError to be thrown. Here is a more detailed sequence:
stdout.read(16384)
file_read(16384)
fread(16384)
read(16384) returns 12288 bytes
read(4096) returns EINTR, causing glibc to set error bit in
FILE
fread returns 12288 bytes
file_read returns 12288 bytes
stdout.read returns 12288 bytes
stdout.read(16384)
file_read(16384)
fread(16384)
read(16384) returns 1266 bytes
read(15118) returns 0, setting EOF bit in FILE
fread returns 1266 bytes
file_read returns 1266 bytes
stdout.read returns 1266 bytes
stdout.read(16384)
file_read(16384)
fread(16384)
fread returns 0
file_read notes 0 return value and checks ferror()
ferror() returns true (due to EINTR, way back in the first call)
file_read sets up exception and returns
stdout.read throws IOError
So, any ideas as to who is at fault? Should glibc see EINTR
and not bother setting the error bit? Should python check feof() in
preference to ferror()? Should I be setting up signal handlers to
restart the read system call? Any ideas are appreciated.
Thanks,
Chris
More information about the Python-list
mailing list