Upgrade to Pro — share decks privately, control downloads, hide ads and more …

PyConZA 2015: "Racy Interrupt Handling" by Bruce Merry

Pycon ZA
October 01, 2015

PyConZA 2015: "Racy Interrupt Handling" by Bruce Merry

A lightning talk on race conditions in Python's interrupt handling and how to successfully avoid these using asyncio.

Pycon ZA

October 01, 2015
Tweet

More Decks by Pycon ZA

Other Decks in Programming

Transcript

  1. POSIX Interrupt Handling in CPython 1 OS jumps main thread

    to C handler 2 Handler sets a flag to indicate interrupt happened 3 Handler requests interpreter to run PyErr_CheckSignals as soon as convenient 4 Main thread continues where it was interrupted Later, PyErr_CheckSignals runs the Python handler or raises KeyboardInterrupt. 2 / 5
  2. How Python Wraps Blocking System Calls The pattern is 1

    Drop the GIL 2 Make the system call 3 Reacquire the GIL 4 If the system call was interrupted, call PyErr_CheckSignals If signal handler raised an exception, bail out Otherwise, go back to step 1 (PEP 0475). 3 / 5
  3. How Python Wraps Blocking System Calls The pattern is 1

    Drop the GIL 2 Make the system call 3 Reacquire the GIL 4 If the system call was interrupted, call PyErr_CheckSignals If signal handler raised an exception, bail out Otherwise, go back to step 1 (PEP 0475). signal delivered here is okay 3 / 5
  4. How Python Wraps Blocking System Calls The pattern is 1

    Drop the GIL 2 Make the system call 3 Reacquire the GIL 4 If the system call was interrupted, call PyErr_CheckSignals If signal handler raised an exception, bail out Otherwise, go back to step 1 (PEP 0475). signal delivered here is okay signal delivered here causes race 3 / 5
  5. Alternative: Wakeup File Descriptor 1 OS jumps main thread to

    C handler 2 Handler sets a flag to indicate interrupt happened 3 Handler requests interpreter to run PyErr_CheckSignals as soon as convenient 4 Handler writes a byte to a file descriptor 5 Main thread continues where it was interrupted 4 / 5
  6. Using The Wakeup FD To avoid the race condition: Create

    a pipe, set write end as wakeup FD Eliminate all blocking calls, except select/poll Include the read end of the wakeup FD in the call Remember to consume the byte written Good News Everyone: tornado and asyncio do this 5 / 5
  7. Using The Wakeup FD To avoid the race condition: Create

    a pipe, set write end as wakeup FD Eliminate all blocking calls, except select/poll Include the read end of the wakeup FD in the call Remember to consume the byte written Good News Everyone: tornado and asyncio do this 5 / 5