[issue25482] signal.set_wakeup_fd() doesn't work if the signal don't have handler

Atsuo Ishimoto report at bugs.python.org
Thu Oct 29 10:44:24 EDT 2015


Atsuo Ishimoto added the comment:

> Benjamin Peterson added the comment:
> 
> The OP probably wants something like the Linux-specific signalfd() syscall.

Yes.

Long explanation:

I have an console text editor written in Python/curses(http://kaaedit.github.io/).

This editor didn't work with Python 3.5 because select.select() stop raising InterruptedError.

Following is sample code to reproduce. This code displays size of terminal. If you resize your terminal, screen is updated and new size is displayed.

---------------------------

import curses, select, sys

def main(stdscr):
    i=0
    while True:
        y, x = stdscr.getmaxyx()
        stdscr.addstr(i % 10, 0, "%d x:%d y:%d" % (i, x, y))
        i+=1
        stdscr.refresh()
        try:
            s=select.select([sys.stdin], [], [])   # wait for user input and some sockets.
        except InterruptedError:
            stdscr.addstr(i % 10, 0, "%d InterruptedError" % i)
            i+=1
            continue
        try:
            c=stdscr.get_wch()
        except curses.error:
            stdscr.addstr(i % 10, 0, "%d curses.error" % i)
            i+=1
            continue
        if c == 'q':
            break

curses.wrapper(main)

---------------------------

Resizing terminal generates SIGIWNCH signal. In Python 3.4, select.select() raises InterruptedError when the signal sent. Also, Ncurses library catches the signal and update internal data to reflect new terminal size.

To detect resizing in Python 3.5, I had to set signal handler for SIGWINCH as following sample. 

---------------
import curses, select, sys, signal, os

rfd, wfd = os.pipe()
os.set_blocking(wfd, False)

def f(*args): pass
signal.signal(signal.SIGWINCH, f)
signal.set_wakeup_fd(wfd)

def main(stdscr):
    i=0
    while True:
        y, x = stdscr.getmaxyx()
        stdscr.addstr(i, 0, "%d x:%d y:%d" % (i, x, y))
        i+=1
        stdscr.refresh()
        try:
            s=select.select([sys.stdin, rfd], [], [])
        except InterruptedError:
            stdscr.addstr(i, 0, "%d InterruptedError" % i)
            i+=1
            continue
        try:
            c=stdscr.get_wch()
        except curses.error:
            stdscr.addstr(i, 0, "%d curses.error" % i)
            i+=1
            continue
        if c == 'q':
            break

curses.wrapper(main)
-------------

This code doesn't display updated size of terminal because SIGWINCH signal is not sent to nurses library. I have to call curses.resizeterm() manually to tell new terminal size to nurses.

I don't know this is common situation or not, but In general, it is not safe to set signal handler when the signal is used by third-party library.

----------

_______________________________________
Python tracker <report at bugs.python.org>
<http://bugs.python.org/issue25482>
_______________________________________


More information about the Python-bugs-list mailing list