tags:

views:

27

answers:

1

What are the disadvantages to using signal.alert to timeout Python I/O?

I ask because I have found that socket.settimeout isn't entirely reliable[0] and I'd like finer control over the timeouts for different operations[1].

So, as far as I can tell, the drawbacks are:

  • Added signal call overhead (but if you're doing I/O, this shouldn't be surprising)
  • It can get "more complex" if the application is using threading (but if threading is already being used, spawning a monitor thread would be easier)

Am I missing anything?

[0]: for example, it won't timeout slow DNS lookups.

[1]: for example, I want some reads to have a short timeout, while other reads should have a longer timeout.

+1  A: 

You will likely not get far when using signals and threads together. From the signal documentation:

... only the main thread can set a new signal handler, and the main thread will be the only one to receive signals (this is enforced by the Python signal module, even if the underlying thread implementation supports sending signals to individual threads)...

As far as drawbacks go, the interpreter will only call the signal handler after the interpreter returns to executing in the main thread context. If you have a long-running C extension call (SQL query, system I/O operation, etc) then SIGINT and SIGTERM signals will not get handled until after they return. If you have strict timing requirements that you are enforcing, then this will not help. The best way I have come up for getting around this is to distribute tasks to a child process, use SIGKILL to kill the child process on a timeout, and then create a replacement child process (a custom process pool).

Also, if you want to use the signal handler as a way of jumping out of a code block via asynchronously-raised exceptions, there is no guarantee for the sanity of your program state. The exception itself could even end up getting raised in unintended places.

For your needs with socket programming, you should start with using non-blocking I/O and a select loop to poll for readiness. Or you can use the asyncore module or the non-standard twisted library which abstract away a lot of those details.

Jeremy Brown