KEY_RESIZE not returned from getch() when xterm is resized

后端 未结 1 975
谎友^
谎友^ 2021-01-24 11:28

I am using Python 3.7 on a Debian Linux 9 box with the standard readline and curses modules. The following code should output \'True\' when run inside an xterm and the xterm is

相关标签:
1条回答
  • 2021-01-24 11:30

    In a quick check with strace, I can see that something resets the SIGWINCH handler back to SIG_DFL (no action) after ncurses sets its handler for SIGWINCH. The symbol table of readline has these relevant entrypoints:

    _rl_block_sigwinch
    _rl_redisplay_after_sigwinch
    _rl_release_sigwinch
    _rl_sigwinch_resize_terminal
    rl_catch_sigwinch
    

    The documentation for readline notes

        o A new variable, rl_catch_sigwinch, is available to application
          writers to indicate to readline whether or not it should install its
          own signal handler for SIGWINCH, which will chain to the calling
          applications's SIGWINCH handler, if one is installed;
    

    However, reading the source for libpython3.5, it appears that the developer did not take that into account:

    /* Helper to initialize GNU readline properly. */
    
    static void
    setup_readline(readlinestate *mod_state)
    {
    ...
        rl_readline_name = "python";
        /* Force rebind of TAB to insert-tab */
        rl_bind_key('\t', rl_insert);
        /* Bind both ESC-TAB and ESC-ESC to the completion function */
        rl_bind_key_in_map ('\t', rl_complete, emacs_meta_keymap);
        rl_bind_key_in_map ('\033', rl_complete, emacs_meta_keymap);
    #ifdef HAVE_RL_RESIZE_TERMINAL
        /* Set up signal handler for window resize */
        sigwinch_ohandler = PyOS_setsig(SIGWINCH, readline_sigwinch_handler);
    #endif
    

    This change in 2016 appears to be related to the problem you're seeing (offhand, it looks like a new problem was introduced without solving the old one). If the signal-handler added for readline doesn't chain over to the one in ncurses, then the latter's no longer used and ncurses cannot return KEY_RESIZE. Also—if readline sets up its handler first, ncurses won't set up its handler.

    The latter seems to be the case: the import readline calls the module initialization which sets up a signal handler. The ncurses signal handler is initialized when the Python curses wrapper calls initscr. That's not done in PyInit__curses (the function called on import curses) because that would clear the screen. Alternatively, ncurses would initialize its signal handler if newterm was called (which would not clear the screen), but Python doesn't do that.

    You could work around this by loading the ncurses (or ncursesw!) library and calling newterm followed by endwin, doing that before the import statements. That seems like a lot of work. I'd recommend opening a bug report.

    For reference:

    • #23735 - Readline not adjusting width after resize with 6.3
    • Signal Handlers, in ncurses documentation.
    0 讨论(0)
提交回复
热议问题