Automatically restarting system calls?

Dan Stromberg dstromberglists at gmail.com
Sun Jun 15 21:06:48 CEST 2008


On Sat, 14 Jun 2008 10:04:15 -0700, Rhamphoryncus wrote:

> On Jun 13, 10:41 am, Dan Stromberg <dstrombergli... at gmail.com> wrote:
>> I wrote a script(1) replacement in python
>> (http://stromberg.dnsalias.org/ ~dstromberg/pypty/), but I'm
>> encountering a problem in it.
>>
>> I think I know the solution to the problem, but I'd've thought python
>> was high level enough that this solution isn't required, so I wanted to
>> inquire about it here.
>>
>> Specifically, the program has a signal handler for window size changes.
>> And if the window is resized during an os.write() (for example), I get
>> a python exception about needing to restart the system call.
>>
>> In C, I know you're supposed to wrap your system calls with while loops
>> until you don't get an ERESTART, but does one really need to wrap all
>> of one's os.write()'s (for example) with such while loops in python?
> 
> Unfortunately, signals are sometimes used to intentionally interrupt
> system calls, so we can't always loop on ERESTART.
> 
> However, os.write() is a low level API.  Maybe file.write() or
> socket.send() would be a little more robust?

Hmmm...  How about an option with a default value of True or False, that 
would control such looping?

BTW, it seems I'm getting EINTR, not ERESTART.

I perhaps could use file.write(), but I'm not confident that's the case, 
because I'm using select.select(), and I'm getting EINTR's not just in 
os.write() but also select.select() and tty.setraw(), so far.

The worst part is, I don't really know which python functions require 
such loops and which don't, or even what those exceptions will look like 
- that is, until I see a real world example.  So as the errors come up in 
real life, I'm wrapping my functions with:

def maybe_restarted_syscall(fn, loop_exc, loop_errnos):
   while 1:
      try:
         result = fn()
      except loop_exc, (errno, error_string):
         if errno in loop_errnos:
            continue
         else:
            sys.stderr.write('%s: %s\n' % (sys.argv[0], error_string))
            raise
      else:
         break
   return result

...and calling it like (for example) :

maybe_restarted_syscall(lambda : select.select([stdin, fd], [], []), 
select.error, [ errno.EINTR ])

Is there some way of being a little more proactive with these errors?

Thanks!




More information about the Python-list mailing list