Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

a couple of read_key_without_echo() fixes #1146

Closed

Conversation

phillipwood
Copy link

@phillipwood phillipwood commented Feb 16, 2022

I have added a new patch to the beginning of the series that fixes a case where we did not call restore_term() when leaving read_key_without_echo(). I have also reworded the commit message to patch 2 as SIGINT is actually ignored while the editor is running (we should probably change that code to use wait_after_clean instead).

Cover letter for V1:

Fix a couple of bugs I noticed when using the builtin "add -p" with interactive.singlekey=true. The first patch is a general fix for the terminal save/restore functionality which forgot to call sigchain_pop() when it restored the terminal. The last two fix reading single keys in non-canonical mode by making sure we wait for an initial key press and only read one byte at a time from the underlying file descriptor.

Note that these are untested on windows beyond our CI compiling them

Cc: Johannes Schindelin Johannes.Schindelin@gmx.de
Cc: Carlo Marcelo Arenas Belón carenas@gmail.com
cc: Phillip Wood phillip.wood123@gmail.com

@phillipwood
Copy link
Author

/submit

@gitgitgadget
Copy link

gitgitgadget bot commented Feb 16, 2022

Submitted as pull.1146.git.1645008873.gitgitgadget@gmail.com

To fetch this version into FETCH_HEAD:

git fetch https://github.com/gitgitgadget/git/ pr-1146/phillipwood/wip/add-p-vmin-v2-v1

To fetch this version to local tag pr-1146/phillipwood/wip/add-p-vmin-v2-v1:

git fetch --no-tags https://github.com/gitgitgadget/git/ tag pr-1146/phillipwood/wip/add-p-vmin-v2-v1

@@ -11,7 +11,7 @@
static void restore_term_on_signal(int sig)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On the Git mailing list, Junio C Hamano wrote (reply to this):

"Phillip Wood via GitGitGadget" <gitgitgadget@gmail.com> writes:

> From: Phillip Wood <phillip.wood@dunelm.org.uk>
>
> If VMIN and VTIME are both set to zero then the terminal performs
> non-blocking reads which means that read_key_without_echo() returns
> EOF if there is no key press pending. This results in the user being
> unable to select anything when running "git add -p".  Fix this by
> explicitly setting VMIN and VTIME when enabling non-canonical mode.

Makes sense.

>
> Signed-off-by: Phillip Wood <phillip.wood@dunelm.org.uk>
> ---
>  compat/terminal.c | 10 +++++++++-
>  1 file changed, 9 insertions(+), 1 deletion(-)
>
> diff --git a/compat/terminal.c b/compat/terminal.c
> index 20803badd03..d882dfa06e3 100644
> --- a/compat/terminal.c
> +++ b/compat/terminal.c
> @@ -57,6 +57,10 @@ static int disable_bits(tcflag_t bits)
>  	t = old_term;
>  
>  	t.c_lflag &= ~bits;
> +	if (bits & ICANON) {
> +		t.c_cc[VMIN] = 1;
> +		t.c_cc[VTIME] = 0;
> +	}

Quite sensible.  I wonder if we can simplify the "are we looking at
an ESC that is the first byte of a multi-byte control sequence?"
logic in the caller by using inter-character delay, but it is
probably better to go one step at a time like this patch does.

>  	if (!tcsetattr(term_fd, TCSAFLUSH, &t))
>  		return 0;
>  
> @@ -159,7 +163,11 @@ static int disable_bits(DWORD bits)
>  
>  		if (bits & ENABLE_LINE_INPUT) {
>  			string_list_append(&stty_restore, "icanon");
> -			strvec_push(&cp.args, "-icanon");
> +			/*
> +			 * POSIX allows VMIN and VTIME to overlap with VEOF and
> +			 * VEOL - let's hope that is not the case on windows.
> +			 */
> +			strvec_pushl(&cp.args, "-icanon", "min", "1", "time", "0", NULL);

Interesting.  So each call to read_key_without_echo() ends up being
a run_command("stty -icanon min 1 time 0") followed by a read
followed by another "stty".

At least while in -icanon mode, VEOF and VEOL do not take effect,
and the potential overlap would not matter.  It really depends on
what happens upon restore.

Do we have similar "let's hope" on the tcsetattr() side, too?

>  		}
>  
>  		if (bits & ENABLE_ECHO_INPUT) {

Thanks.

@@ -70,6 +70,8 @@ void init_add_i_state(struct add_i_state *s, struct repository *r)
&s->interactive_diff_algorithm);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On the Git mailing list, Junio C Hamano wrote (reply to this):

"Phillip Wood via GitGitGadget" <gitgitgadget@gmail.com> writes:

> diff --git a/add-interactive.c b/add-interactive.c
> index 6498ae196f1..ad78774ca26 100644
> --- a/add-interactive.c
> +++ b/add-interactive.c
> @@ -70,6 +70,8 @@ void init_add_i_state(struct add_i_state *s, struct repository *r)
>  			      &s->interactive_diff_algorithm);
>  
>  	git_config_get_bool("interactive.singlekey", &s->use_single_key);
> +	if (s->use_single_key)
> +		setbuf(stdin, NULL);

OK.  Will queue.  Thanks.

>  }
>  
>  void clear_add_i_state(struct add_i_state *s)

@gitgitgadget
Copy link

gitgitgadget bot commented Feb 16, 2022

This branch is now known as pw/single-key-interactive.

@gitgitgadget
Copy link

gitgitgadget bot commented Feb 16, 2022

This patch series was integrated into seen via git@c39da26.

@gitgitgadget gitgitgadget bot added the seen label Feb 16, 2022
@gitgitgadget
Copy link

gitgitgadget bot commented Feb 17, 2022

This patch series was integrated into seen via git@a00a850.

@gitgitgadget
Copy link

gitgitgadget bot commented Feb 18, 2022

This patch series was integrated into seen via git@788a220.

@gitgitgadget
Copy link

gitgitgadget bot commented Feb 18, 2022

This patch series was integrated into seen via git@2f15c70.

@gitgitgadget
Copy link

gitgitgadget bot commented Feb 18, 2022

There was a status update in the "New Topics" section about the branch pw/single-key-interactive on the Git mailing list:

The single-key interactive operation used by "git add -p" has been
made more robust.

Will merge to 'next'?
source: <pull.1146.git.1645008873.gitgitgadget@gmail.com>

@gitgitgadget
Copy link

gitgitgadget bot commented Feb 18, 2022

This patch series was integrated into seen via git@74e0049.

@gitgitgadget
Copy link

gitgitgadget bot commented Feb 21, 2022

This patch series was integrated into seen via git@e53fb7a.

@gitgitgadget
Copy link

gitgitgadget bot commented Feb 22, 2022

This patch series was integrated into seen via git@21a4e89.

Break out of the loop to ensure restore_term() is called before
returning.

Signed-off-by: Phillip Wood <phillip.wood@dunelm.org.uk>
When disable_bits() changes the terminal attributes it uses
sigchain_push_common() to restore the terminal if a signal is received
before restore_term() is called. However there is no corresponding
call to sigchain_pop_common() when the settings are restored so the
signal handler is left on the sigchain stack. This leaves the stack
unbalanced so code such as

sigchain_push_common(my_handler);
...
read_key_without_echo(...);
...
sigchain_pop_common();

pops the handler pushed by disable_bits() rather than the one it
intended to. Additionally "git add -p" changes the terminal settings
every time it reads a key press so the stack can grow significantly.

In order to fix this save_term() now sets up the signal handler so
restore_term() can unconditionally call sigchain_pop_common(). There
are no callers of save_term() outside of terminal.c as the only
external caller was removed by e3f7e01 ("Revert "editor: save and
reset terminal after calling EDITOR"", 2021-11-22). Any future callers
of save_term() should benefit from having the signal handler set up
for them.

Signed-off-by: Phillip Wood <phillip.wood@dunelm.org.uk>
If VMIN and VTIME are both set to zero then the terminal performs
non-blocking reads which means that read_key_without_echo() returns
EOF if there is no key press pending. This results in the user being
unable to select anything when running "git add -p".  Fix this by
explicitly setting VMIN and VTIME when enabling non-canonical mode.

Signed-off-by: Phillip Wood <phillip.wood@dunelm.org.uk>
The builtin "add -p" reads the key "F2" as three separate keys "^[",
"O" and "Q". The "Q" causes it to quit which is probably not what the
user was expecting. This is because it uses poll() to check for
pending input when reading escape sequences but reads the input with
getchar() which is buffered by default and so hoovers up all the
pending input leading poll() think there isn't anything pending. Fix
this by calling setbuf() to disable input buffering if
interactive.singlekey is set.

Looking at the comment above mingw_getchar() in terminal.c I wonder if
that function is papering over this bug and could be removed.
Unfortunately I don't have access to windows to test that.

Signed-off-by: Phillip Wood <phillip.wood@dunelm.org.uk>
@phillipwood
Copy link
Author

/submit

@gitgitgadget
Copy link

gitgitgadget bot commented Feb 22, 2022

Submitted as pull.1146.v2.git.1645556015.gitgitgadget@gmail.com

To fetch this version into FETCH_HEAD:

git fetch https://github.com/gitgitgadget/git/ pr-1146/phillipwood/wip/add-p-vmin-v2-v2

To fetch this version to local tag pr-1146/phillipwood/wip/add-p-vmin-v2-v2:

git fetch --no-tags https://github.com/gitgitgadget/git/ tag pr-1146/phillipwood/wip/add-p-vmin-v2-v2

@gitgitgadget
Copy link

gitgitgadget bot commented Feb 23, 2022

On the Git mailing list, Junio C Hamano wrote (reply to this):

"Phillip Wood via GitGitGadget" <gitgitgadget@gmail.com> writes:

> I have added a new patch to the beginning of the series that fixes a case
> where we did not call restore_term() when leaving read_key_without_echo(). I
> have also reworded the commit message to patch 2 as SIGINT is actually
> ignored while the editor is running (we should probably change that code to
> use wait_after_clean instead).

All patches looked good.  Thanks.

Let's mark it for 'next' and below soonish.

>
> Cover letter for V1:
>
> Fix a couple of bugs I noticed when using the builtin "add -p" with
> interactive.singlekey=true. The first patch is a general fix for the
> terminal save/restore functionality which forgot to call sigchain_pop() when
> it restored the terminal. The last two fix reading single keys in
> non-canonical mode by making sure we wait for an initial key press and only
> read one byte at a time from the underlying file descriptor.
>
> Note that these are untested on windows beyond our CI compiling them
>
> Phillip Wood (4):
>   terminal: always reset terminal when reading without echo
>   terminal: pop signal handler when terminal is restored
>   terminal: set VMIN and VTIME in non-canonical mode
>   add -p: disable stdin buffering when interactive.singlekey is set
>
>  add-interactive.c |  2 ++
>  compat/terminal.c | 29 +++++++++++++++++++++++------
>  compat/terminal.h |  8 ++++++++
>  3 files changed, 33 insertions(+), 6 deletions(-)
>
>
> base-commit: b80121027d1247a0754b3cc46897fee75c050b44
> Published-As: https://github.com/gitgitgadget/git/releases/tag/pr-1146%2Fphillipwood%2Fwip%2Fadd-p-vmin-v2-v2
> Fetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-1146/phillipwood/wip/add-p-vmin-v2-v2
> Pull-Request: https://github.com/gitgitgadget/git/pull/1146
>
> Range-diff vs v1:
>
>  -:  ----------- > 1:  45609d61afc terminal: always reset terminal when reading without echo
>  1:  9a3c2cea0f9 ! 2:  0020953f1cf terminal: pop signal handler when terminal is restored
>      @@ Commit message
>           external caller was removed by e3f7e01b50 ("Revert "editor: save and
>           reset terminal after calling EDITOR"", 2021-11-22). Any future callers
>           of save_term() should benefit from having the signal handler set up
>      -    for them. For example if we reinstate the code to protect against an
>      -    editor failing to restore the terminal attributes we would want that
>      -    code to restore the terminal attributes on SIGINT. (As an aside
>      -    run_command() installs a signal handler that waits for the child
>      -    before re-raising the signal so we would be guaranteed to restore the
>      -    settings after the child has exited.)
>      +    for them.
>       
>           Signed-off-by: Phillip Wood <phillip.wood@dunelm.org.uk>
>       
>  2:  02009172e08 = 3:  7ae9b236554 terminal: set VMIN and VTIME in non-canonical mode
>  3:  6d8423b6e1e = 4:  39b061a471b add -p: disable stdin buffering when interactive.singlekey is set

@gitgitgadget
Copy link

gitgitgadget bot commented Feb 24, 2022

This patch series was integrated into seen via git@a2c89e0.

@gitgitgadget
Copy link

gitgitgadget bot commented Feb 24, 2022

There was a status update in the "Cooking" section about the branch pw/single-key-interactive on the Git mailing list:

The single-key interactive operation used by "git add -p" has been
made more robust.

Will merge to 'next'?
source: <pull.1146.v2.git.1645556015.gitgitgadget@gmail.com>

@gitgitgadget
Copy link

gitgitgadget bot commented Feb 26, 2022

This patch series was integrated into seen via git@91a83ab.

@gitgitgadget
Copy link

gitgitgadget bot commented Feb 26, 2022

There was a status update in the "Cooking" section about the branch pw/single-key-interactive on the Git mailing list:

The single-key interactive operation used by "git add -p" has been
made more robust.

Will merge to 'next'?
source: <pull.1146.v2.git.1645556015.gitgitgadget@gmail.com>

@gitgitgadget
Copy link

gitgitgadget bot commented Feb 26, 2022

This patch series was integrated into seen via git@e5de67c.

@gitgitgadget
Copy link

gitgitgadget bot commented Mar 1, 2022

This patch series was integrated into seen via git@ef3d53d.

@gitgitgadget
Copy link

gitgitgadget bot commented Mar 1, 2022

There was a status update in the "Cooking" section about the branch pw/single-key-interactive on the Git mailing list:

The single-key interactive operation used by "git add -p" has been
made more robust.

Will merge to 'next'?
source: <pull.1146.v2.git.1645556015.gitgitgadget@gmail.com>

@gitgitgadget
Copy link

gitgitgadget bot commented Mar 1, 2022

This patch series was integrated into seen via git@55febcf.

@gitgitgadget
Copy link

gitgitgadget bot commented Mar 8, 2022

This patch series was integrated into seen via git@a79eab9.

@gitgitgadget
Copy link

gitgitgadget bot commented Mar 9, 2022

This patch series was integrated into seen via git@c18fafa.

@gitgitgadget
Copy link

gitgitgadget bot commented Mar 9, 2022

This patch series was integrated into seen via git@65e035b.

@gitgitgadget
Copy link

gitgitgadget bot commented Mar 10, 2022

This patch series was integrated into seen via git@32f3ac2.

@gitgitgadget
Copy link

gitgitgadget bot commented Mar 11, 2022

This patch series was integrated into seen via git@3615c3d.

@gitgitgadget
Copy link

gitgitgadget bot commented Mar 13, 2022

This patch series was integrated into seen via git@4fbc4d8.

@gitgitgadget
Copy link

gitgitgadget bot commented Mar 14, 2022

This patch series was integrated into seen via git@25bd290.

@gitgitgadget
Copy link

gitgitgadget bot commented Mar 14, 2022

This patch series was integrated into next via git@02fd6ac.

@gitgitgadget gitgitgadget bot added the next label Mar 14, 2022
@gitgitgadget
Copy link

gitgitgadget bot commented Mar 14, 2022

There was a status update in the "Cooking" section about the branch pw/single-key-interactive on the Git mailing list:

The single-key interactive operation used by "git add -p" has been
made more robust.

Will merge to 'master'.
source: <pull.1146.v2.git.1645556015.gitgitgadget@gmail.com>

@gitgitgadget
Copy link

gitgitgadget bot commented Mar 15, 2022

This patch series was integrated into seen via git@64c0dbf.

@gitgitgadget
Copy link

gitgitgadget bot commented Mar 16, 2022

This patch series was integrated into seen via git@4cac652.

@gitgitgadget
Copy link

gitgitgadget bot commented Mar 17, 2022

This patch series was integrated into seen via git@96ea03b.

@gitgitgadget
Copy link

gitgitgadget bot commented Mar 17, 2022

There was a status update in the "Cooking" section about the branch pw/single-key-interactive on the Git mailing list:

The single-key interactive operation used by "git add -p" has been
made more robust.

Will merge to 'master'.
source: <pull.1146.v2.git.1645556015.gitgitgadget@gmail.com>

@gitgitgadget
Copy link

gitgitgadget bot commented Mar 17, 2022

This patch series was integrated into seen via git@352c3f0.

@gitgitgadget
Copy link

gitgitgadget bot commented Mar 17, 2022

This patch series was integrated into seen via git@0efe6de.

@gitgitgadget
Copy link

gitgitgadget bot commented Mar 18, 2022

This patch series was integrated into seen via git@b77a4a5.

@gitgitgadget
Copy link

gitgitgadget bot commented Mar 21, 2022

This patch series was integrated into seen via git@cc1779e.

@gitgitgadget
Copy link

gitgitgadget bot commented Mar 22, 2022

This patch series was integrated into seen via git@214919b.

@gitgitgadget
Copy link

gitgitgadget bot commented Mar 22, 2022

This patch series was integrated into master via git@214919b.

@gitgitgadget
Copy link

gitgitgadget bot commented Mar 22, 2022

This patch series was integrated into next via git@214919b.

@gitgitgadget gitgitgadget bot added the master label Mar 22, 2022
@gitgitgadget
Copy link

gitgitgadget bot commented Mar 22, 2022

Closed via 214919b.

@gitgitgadget gitgitgadget bot closed this Mar 22, 2022
@gitgitgadget
Copy link

gitgitgadget bot commented Mar 22, 2022

On the Git mailing list, Carlo Arenas wrote (reply to this):

On Thu, Feb 24, 2022 at 6:30 AM Phillip Wood <phillip.wood123@gmail.com> wrote:
> That sounds good. I've got a couple more patches based on top of these
> which hopefully fix the remaining problems (notably the macos poll()
> bug). I'll polish and post them next week. Once those are in I hope
> we'll be able to enable the builtin "add -p" by default.

As this topic just hit master noticed (I apologize for not doing it
sooner) the macOS problem (tested in 10.15.7) was gone (suspect fixed
with 1/4) and therefore enabling the builtin by default as proposed
originally by dscho could proceed without the additional series.

Carlo

@gitgitgadget
Copy link

gitgitgadget bot commented Mar 23, 2022

On the Git mailing list, Junio C Hamano wrote (reply to this):

Carlo Arenas <carenas@gmail.com> writes:

> On Thu, Feb 24, 2022 at 6:30 AM Phillip Wood <phillip.wood123@gmail.com> wrote:
>> That sounds good. I've got a couple more patches based on top of these
>> which hopefully fix the remaining problems (notably the macos poll()
>> bug). I'll polish and post them next week. Once those are in I hope
>> we'll be able to enable the builtin "add -p" by default.
>
> As this topic just hit master noticed (I apologize for not doing it
> sooner) the macOS problem (tested in 10.15.7) was gone (suspect fixed
> with 1/4) and therefore enabling the builtin by default as proposed
> originally by dscho could proceed without the additional series.

As long as it is a belated success report, nobody would mind.  A
belated failure report would be a cause of sorrow and grief, but
even then, it is better to have it late than never.

Thanks for testing.

@gitgitgadget
Copy link

gitgitgadget bot commented Mar 24, 2022

On the Git mailing list, Johannes Schindelin wrote (reply to this):

Hi,

On Wed, 23 Mar 2022, Junio C Hamano wrote:

> Carlo Arenas <carenas@gmail.com> writes:
>
> > On Thu, Feb 24, 2022 at 6:30 AM Phillip Wood <phillip.wood123@gmail.com> wrote:
> >> That sounds good. I've got a couple more patches based on top of these
> >> which hopefully fix the remaining problems (notably the macos poll()
> >> bug). I'll polish and post them next week. Once those are in I hope
> >> we'll be able to enable the builtin "add -p" by default.
> >
> > As this topic just hit master noticed (I apologize for not doing it
> > sooner) the macOS problem (tested in 10.15.7) was gone (suspect fixed
> > with 1/4) and therefore enabling the builtin by default as proposed
> > originally by dscho could proceed without the additional series.
>
> As long as it is a belated success report, nobody would mind.  A
> belated failure report would be a cause of sorrow and grief, but
> even then, it is better to have it late than never.
>
> Thanks for testing.

FWIW I tried to reproduce the reported issues, but since I do not have any
hardware running macOS anymore, I only had the avenue to debug via `tmate`
on one of GitHub Actions' macOS agents, but the problem did not reproduce
for me via SSH.

I am grateful for the great work put in by Carlo and Phillip to fix these
issues.

Thanks,
Dscho

@gitgitgadget
Copy link

gitgitgadget bot commented Mar 28, 2022

On the Git mailing list, Phillip Wood wrote (reply to this):

Hi Carlo

On 22/03/2022 20:18, Carlo Arenas wrote:
> On Thu, Feb 24, 2022 at 6:30 AM Phillip Wood <phillip.wood123@gmail.com> wrote:
>> That sounds good. I've got a couple more patches based on top of these
>> which hopefully fix the remaining problems (notably the macos poll()
>> bug). I'll polish and post them next week. Once those are in I hope
>> we'll be able to enable the builtin "add -p" by default.
> > As this topic just hit master noticed (I apologize for not doing it
> sooner) the macOS problem (tested in 10.15.7) was gone (suspect fixed
> with 1/4) and therefore enabling the builtin by default as proposed
> originally by dscho could proceed without the additional series.

Thanks for testing this series

Best Wishes

Phillip

@gitgitgadget
Copy link

gitgitgadget bot commented Mar 28, 2022

User Phillip Wood <phillip.wood123@gmail.com> has been added to the cc: list.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

1 participant