Question about read() behavior and EINTR

Chris Jaeger cjaeger at ensim.com
Wed Oct 10 00:08:36 CEST 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