bug-bash
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: fg via keybind modifies tty settings


From: Chet Ramey
Subject: Re: fg via keybind modifies tty settings
Date: Thu, 7 Nov 2024 14:19:54 -0500
User-agent: Mozilla Thunderbird

On 11/5/24 1:21 AM, David Moberg wrote:


Den ons 16 okt. 2024 17:43Chet Ramey <chet.ramey@case.edu <mailto:chet.ramey@case.edu>> skrev:

    On 10/13/24 12:10 PM, David Moberg wrote:
     > A new issue popped up with these changes. After second time of
    suspend and
     > foreground with binding, the tty will not react to control keys but
    instead
     > print them on the prompt.

    In general, this can't work, given a well-behaved process like vim that
    modifies the tty settings.

     > | start vim
     >    ctrl-z (to suspend)
     >    ctrl-a (bound to `fg` to bring to foregound)
     >    ctrl-z (to suspend a 2nd time)
     >    # broken state (but I dont see anything changed in the output of
    `stty
     > -a`)
     >    # ctrl-a prints ^A (instead of executing fg)
     >    # <UP> prints ^[[A (Instead of invoking history)
     >
     > Issue 1: control codes are printed to prompt

    The important thing to remember is that the shell saves the tty settings
    when it starts up and after each forked command exits, so it can set them
    for child processes. This is how it can make stty settings stick while
    still setting the terminal for readline. It doesn't do this if it's running
    a command from a readline key binding.

    It restores the terminal attributes to these saved settings after a process
    exits due to a signal or stops so a misbehaving process doesn't corrupt
    the terminal.

    Let's use the following shorthand:

    R = tty settings for readline (-icanon)
    V = tty settings for vim (-icanon)
    S = tty settings shell inherited or saved (icanon)

    Here's what happens:

    shell saves tty settings S
    readline sets tty settings R
    readline reads "vim ...\n"
    shell sets tty to S
    shell execs vim
    vim saves tty settings S

    vim sets tty settings V
    vim reads ^Z
    vim sets tty settings S (saved)

    vim sends itself SIGTSTP
    shell catches stopped child

    shell sets tty settings S (the saved tty settings because the process
    stopped)
    readline sets tty settings R
    readline reads ^A
    shell sends SIGCONT due to running `fg' from the `bind -x' binding
             - this is where the shell used to save the terminal settings again
               for later resetting, but it no longer does due to your previous
               report, so S is unchanged

    vim gets SIGCONT
    vim sets tty settings V
    vim reads ^Z
    vim sets tty settings S (saved)

    vim sends itself SIGTSTP
    shell catches stopped child

    shell sets tty settings S (saved tty settings because the process stopped)
             - but it wouldn't matter because vim already set them to S

    readline is still active because this was all a key binding

    Now readline thinks the settings are R, but the settings are S.



So there is no good way of solving this and therefor no way to solve it at all?

The bind -x execution code could restore the terminal settings to icanon
mode before executing the command, and then set them back to what readline
is using (-icanon) before returning. This is not backwards compatible
and would break all the bind -x bindings that assume the terminal is the
way readline set it, so I'm not inclined to do it.

I guess fish and zsh might be misbehaving in other ways, but they seem to handle this detail better. I wonder what the tradeoff is.

Historically, zsh doesn't let child processes change the terminal
settings at all. Look at the `ttyctl' builtin. I don't know what fish
does.


--
``The lyf so short, the craft so long to lerne.'' - Chaucer
                 ``Ars longa, vita brevis'' - Hippocrates
Chet Ramey, UTech, CWRU    chet@case.edu    http://tiswww.cwru.edu/~chet/

Attachment: OpenPGP_signature.asc
Description: OpenPGP digital signature


reply via email to

[Prev in Thread] Current Thread [Next in Thread]