Pylon Signal Processing

I have a pylons project where I need to periodically update some memory structures. This should be done on demand. I decided to come up with a signal handler for this. The user sends SIGUSR1 to the main pylon stream and is processed by the project.

This works, except after processing the signal, the server crashes with the following exception:

 File "/usr/lib/python2.6/SocketServer.py", line 264, in handle_request fd_sets = select.select([self], [], [], timeout) select.error: (4, 'Interrupted system call') 

Can this be fixed?

TIA.

+4
source share
2 answers

Yes, it’s possible, but it’s not easy to use the Python stock libraries. This is because Python translates all OS errors into exceptions. However, the EINTR does indeed have to cause a reuse of the used system call. Whenever you start using signals in Python, you will see this error sporadically.

I have code that fixes this (SafeSocket) by formatting Python modules and adding this functionality. But it should be added wherever system calls are used. So it’s possible, but not easy. But you can use my open source code, it can save you many years .; -)

The main template is this (implemented as a system call decorator):

 # decorator to make system call methods safe from EINTR def systemcall(meth): # have to import this way to avoid a circular import from _socket import error as SocketError def systemcallmeth(*args, **kwargs): while 1: try: rv = meth(*args, **kwargs) except EnvironmentError as why: if why.args and why.args[0] == EINTR: continue else: raise except SocketError as why: if why.args and why.args[0] == EINTR: continue else: raise else: break return rv return systemcallmeth 

You can also just use this around your chosen call.

+5
source

The fix at least works for me, from a 12 year python-dev list

  while True: try: readable, writable, exceptional = select.select(inputs, outputs, inputs, timeout) except select.error, v: if v[0] != errno.EINTR: raise else: break 

The details of the actual selection line are not important ... your line "fd_sets = select.select ([self], [], [], timeout]" should work exactly the same.

An important bit is checking for EINTR and repeating / looping if caught. Oh, and don't forget to import errno.

+2
source

Source: https://habr.com/ru/post/1347691/


All Articles