zsh-workers
 help / color / mirror / code / Atom feed
* Functions registered with zle -F stop being run after a job finishes
@ 2019-03-23 13:55 Roman Perepelitsa
  2019-03-23 18:30 ` Peter Stephenson
  2019-03-25 22:11 ` Roman Perepelitsa
  0 siblings, 2 replies; 7+ messages in thread
From: Roman Perepelitsa @ 2019-03-23 13:55 UTC (permalink / raw)
  To: zsh-workers

[-- Attachment #1: Type: text/plain, Size: 2306 bytes --]

Hi,

tl;dr: There appears to be a bug in zsh. When a background job finishes,
functions registered with zle -F stop running until the user presses a key
(say, [enter] or [esc]) or the shell receives a signal (any signal at all).

Assuming the pristine environment granted by zsh -df, consider the
following piece of code.

mkfifo /tmp/fifoexec {fd}<>/tmp/fifo
( for ((i=1;;++i)); do sleep 1; echo $i; done ) >&$fd &
function f() { zle -I && read -eu $fd }
zle -F $fd f
sleep 5&
( sleep 10; kill -WINCH $$ ) &

It creates a fifo, to which a background job writes consecutive numbers
once a second. It then uses zle -F to register a function that gets called
whenever there is something in the fifo. The function reads and prints the
content of the fifo.

This part of the code produces the following output:

adam%
1
adam%
2
adam%
3

And so on, with one line every second. The code also creates a background
job that doesn’t do anything and finishes after 5 seconds. The expected
behavior is that we’ll keep seeing consecutive numbers on the screen after
this job finishes but that’s not what happens. In fact, the output stops.

adam%
4
adam%
[2]  + done       sleep 5
adam%

If we hit [esc] or [enter] at this point, the missing numbers will appear
all at once and the new numbers will continue being printed once a second.

Instead of pressing a key we can send our shell a signal. It’ll have the
same effect. Any signal will do as long as it doesn’t kill the process. For
example, we can define a signal handler for SIGUSR1 and execute kill -USR1
$pid from another shell. Or, like the code snippet does, we can send
SIGWINCH, taking advantage of its having the default handler that does
nothing.

Here’s the complete output where you can see everything in action:

adam% mkfifo /tmp/fifo
exec {fd}<>/tmp/fifo
( for ((i=1;;++i)); do sleep 1; echo $i; done ) >&$fd &
function f() { zle -I && read -eu $fd }
zle -F $fd f
sleep 5&
( sleep 10; kill -WINCH $$ ) &
[1] 9468
[2] 9469
[3] 9471
adam%
1
adam%
2
adam%
3
adam%
4
adam%
[2]  - done       sleep 5
adam%
5
[3]  + done       ( sleep 10; kill -WINCH $$; )
adam% adam%
6
adam%
7
adam%
8
adam%
9
adam%
10
adam%
11
adam%
12
adam%

And so on.

Roman.

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: Functions registered with zle -F stop being run after a job finishes
  2019-03-23 13:55 Functions registered with zle -F stop being run after a job finishes Roman Perepelitsa
@ 2019-03-23 18:30 ` Peter Stephenson
  2019-03-27 19:01   ` Peter Stephenson
  2019-03-25 22:11 ` Roman Perepelitsa
  1 sibling, 1 reply; 7+ messages in thread
From: Peter Stephenson @ 2019-03-23 18:30 UTC (permalink / raw)
  To: zsh-workers

> tl;dr: There appears to be a bug in zsh. When a background job finishes,
> functions registered with zle -F stop running until the user presses a key
> (say, [enter] or [esc]) or the shell receives a signal (any signal at all).

It's going to be something like the following.  Note I haven't tried
this, except to confirm it compiles, but it looks like you've got a
reliable way of provoking this, and this should give you enough to go on
--- it's 99% certain the problem lies in that for (;;) loop surrounding
the code patched here.

The story is that we try to make sure errors on the -F file descriptors
don't mess up the editor.  The errtry flag exists to say they look
suspect, so we'll try to ensure the user can continue editing even so.
In your case, however, the return value from poll (probably) or select
(in the unlikely event you don't have poll) is simply indicating the
call was interrupted, so we can carry on trying.

Not 100% sure if a "continue" or simply falling through is better here
--- falling through might be better to get any remaining timeout fixed
up, though that doesn't look like a problem in your case, but as the
poll / select didn't give us anything useful it's otherwise better to
continue.

Hope this gives you enough pointers.
pws

diff --git a/Src/Zle/zle_main.c b/Src/Zle/zle_main.c
index 71930f76b..8de8e0121 100644
--- a/Src/Zle/zle_main.c
+++ b/Src/Zle/zle_main.c
@@ -632,7 +632,13 @@ raw_getbyte(long do_keytmout, char *cptr, int full)
 	     * with all fds, then try unsetting the special ones.
 	     */
 	    if (selret < 0 && !errtry) {
-		errtry = 1;
+		if (errno == EINTR) {
+		    /* Continue after interrupt */
+		    errflag &= ~ERRFLAG_INT;
+		} else {
+		    /* Don't trust special FDs */
+		    errtry = 1;
+		}
 		continue;
 	    }
 	    if (selret == 0) {



^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: Functions registered with zle -F stop being run after a job finishes
  2019-03-23 13:55 Functions registered with zle -F stop being run after a job finishes Roman Perepelitsa
  2019-03-23 18:30 ` Peter Stephenson
@ 2019-03-25 22:11 ` Roman Perepelitsa
  2019-03-26  9:22   ` Peter Stephenson
  1 sibling, 1 reply; 7+ messages in thread
From: Roman Perepelitsa @ 2019-03-25 22:11 UTC (permalink / raw)
  To: zsh-workers

[-- Attachment #1: Type: text/plain, Size: 247 bytes --]

> Hope this gives you enough pointers.

I wish all pointers were complete fixes :-) It works great.

Is there something I need to do to ensure this fix is included in the
future zsh releases? Or perhaps you'll apply the patch yourself?

Roman.

>

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: Functions registered with zle -F stop being run after a job finishes
  2019-03-25 22:11 ` Roman Perepelitsa
@ 2019-03-26  9:22   ` Peter Stephenson
  2019-03-26  9:36     ` Roman Perepelitsa
  0 siblings, 1 reply; 7+ messages in thread
From: Peter Stephenson @ 2019-03-26  9:22 UTC (permalink / raw)
  To: zsh-workers

On Mon, 2019-03-25 at 23:11 +0100, Roman Perepelitsa wrote:
> > Hope this gives you enough pointers.
> I wish all pointers were complete fixes :-) It works great.
>  
> Is there something I need to do to ensure this fix is included in the
> future zsh releases? Or perhaps you'll apply the patch yourself?

Nothing more to do; if it works I'll simply put it in.

Cheers
pws


^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: Functions registered with zle -F stop being run after a job finishes
  2019-03-26  9:22   ` Peter Stephenson
@ 2019-03-26  9:36     ` Roman Perepelitsa
  0 siblings, 0 replies; 7+ messages in thread
From: Roman Perepelitsa @ 2019-03-26  9:36 UTC (permalink / raw)
  To: zsh-workers; +Cc: Peter Stephenson

[-- Attachment #1: Type: text/plain, Size: 422 bytes --]

On Tue, Mar 26, 2019 at 10:23 AM Peter Stephenson <p.stephenson@samsung.com>
wrote:

> On Mon, 2019-03-25 at 23:11 +0100, Roman Perepelitsa wrote:
> > Is there something I need to do to ensure this fix is included in the
> > future zsh releases? Or perhaps you'll apply the patch yourself?
>
> Nothing more to do; if it works I'll simply put it in.
>

Awesome! Yes, it works perfectly in the scenario I described.

Roman.

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: Functions registered with zle -F stop being run after a job finishes
  2019-03-23 18:30 ` Peter Stephenson
@ 2019-03-27 19:01   ` Peter Stephenson
  2019-03-28 10:31     ` Roman Perepelitsa
  0 siblings, 1 reply; 7+ messages in thread
From: Peter Stephenson @ 2019-03-27 19:01 UTC (permalink / raw)
  To: zsh-workers

On Sat, 2019-03-23 at 18:30 +0000, Peter Stephenson wrote:
> > tl;dr: There appears to be a bug in zsh. When a background job finishes,
> > functions registered with zle -F stop running until the user presses a key
> > (say, [enter] or [esc]) or the shell receives a signal (any signal at all).
> 
> It's going to be something like the following.

On second thoughts I don't think removing ERRFLAG_INT is a good idea ---
that won't be set in the case in question as there's no user keyboard
interrupt, and if there was one we shouldn't ignore it.  Committed
the following.

pws

modified   Src/Zle/zle_main.c
@@ -632,7 +632,11 @@ raw_getbyte(long do_keytmout, char *cptr, int full)
 	     * with all fds, then try unsetting the special ones.
 	     */
 	    if (selret < 0 && !errtry) {
-		errtry = 1;
+		/* Continue after irrelevant interrupt */
+		if (errno != EINTR) {
+		    /* Don't trust special FDs */
+		    errtry = 1;
+		}
 		continue;
 	    }
 	    if (selret == 0) {



^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: Functions registered with zle -F stop being run after a job finishes
  2019-03-27 19:01   ` Peter Stephenson
@ 2019-03-28 10:31     ` Roman Perepelitsa
  0 siblings, 0 replies; 7+ messages in thread
From: Roman Perepelitsa @ 2019-03-28 10:31 UTC (permalink / raw)
  To: Peter Stephenson; +Cc: zsh-workers

[-- Attachment #1: Type: text/plain, Size: 515 bytes --]

On Wed, Mar 27, 2019 at 8:02 PM Peter Stephenson <
p.w.stephenson@ntlworld.com> wrote:

>
> On second thoughts I don't think removing ERRFLAG_INT is a good idea ---
> that won't be set in the case in question as there's no user keyboard
> interrupt, and if there was one we shouldn't ignore it.  Committed
> the following.
>
> [...]
>

I confirm that this works on my test case.

By the way, any chance you could take a look at
https://www.zsh.org/mla/workers//2019/msg00204.html or ping someone who
might?

Roman.

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2019-03-28 10:32 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-03-23 13:55 Functions registered with zle -F stop being run after a job finishes Roman Perepelitsa
2019-03-23 18:30 ` Peter Stephenson
2019-03-27 19:01   ` Peter Stephenson
2019-03-28 10:31     ` Roman Perepelitsa
2019-03-25 22:11 ` Roman Perepelitsa
2019-03-26  9:22   ` Peter Stephenson
2019-03-26  9:36     ` Roman Perepelitsa

Code repositories for project(s) associated with this public inbox

	https://git.vuxu.org/mirror/zsh/

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).