zsh-workers
 help / color / mirror / code / Atom feed
From: Bart Schaefer <schaefer@brasslantern.com>
To: zsh-workers@zsh.org
Subject: Re: How to misplace an entire pipeline
Date: Mon, 08 Aug 2011 23:10:32 -0700	[thread overview]
Message-ID: <110808231032.ZM2380@torch.brasslantern.com> (raw)
In-Reply-To: <20110808192720.380a3ee7@pws-pc.ntlworld.com>

On Aug 8,  7:27pm, Peter Stephenson wrote:
} Subject: Re: How to misplace an entire pipeline
}
} On Sun, 07 Aug 2011 21:05:07 -0700
} Bart Schaefer <schaefer@brasslantern.com> wrote:
} > -	jobtab[thisjob].stat |= STAT_CURSH|STAT_NOPRINT;
} > +	jobtab[thisjob].stat |= STAT_CURSH;
} > +	if (!jobtab[thisjob].procs)
} > +	    jobtab[thisjob].stat |= STAT_NOPRINT;
} 
} Looks fairly plausible, anyway.

Should that be "if (hasprocs(thisjob))" instead, do you think?

} > When "read" is the tail of the pipe, the above all happens behind the
} > scenes and then the I/O system call gets restarted, which is how the
} > shell ends up stuck.  I'm not sure how to escape from that, except
} > maybe to have zhandler() kill the shell with a different signal from
} > which the system call will not recover.
} 
} I suppose so.  I can hardly believe this ever worked.

It didn't, exactly.  This particular one behaves almost the same in
4.3.9 as it does in recent dev releases.  The main difference is that
in 4.3.9 the ^Z echoes to the terminal; in 4.3.12 there's no feedback
at all.  I haven't figured out how/why that changed.

} > The only obvious thing I can think to do here is to note in zhandler()
} > that we have STAT_CURSH but not list_pipe, and therefore SIGCONT the
} > left-hand-side immediately and return as if no signal had occurred
} > (possibly printing a warning about not being able to suspend the job,
} > which is what happens elsewhere if pipe() or fork() fails).  However,
} > that could lead to a serious busy-loop if somehow TTIN or TTOU was
} > the signal instead of TSTP.
} 
} But we can test if it's TSTP (or STOP)?

Yes, when WSTOPSIG() is defined.  The parent shell never gets the
original signal, it only gets the SIGCHLD and can then examine the
return value from wait3() or whatever system call was available.

SIGSTOP can't be caught or blocked so in that case it's likely the
parent shell has also stopped.  I'm not sure it'd be good behavior
for the shell to auto-resume a process that was hit with STOP, even
if it could.

So, some more about what's going on ...

Near the end of execpline2() there's this snippet:

	/* if another execpline() is invoked because the command is *
	 * a list it must know that we're already in a pipeline     */
	cmdpush(CS_PIPE);
	list_pipe = 1;
	execpline2(state, *state->pc++, how, pipes[0], output, last1);
	list_pipe = old_list_pipe;
	cmdpop();

Somewhere in the call stack beyond this execpline2(), execbuiltin() is
called.  If that returns immediately we climb out of execpline2() and
clear list_pipe and wait for the pipeline at execpline() line 1500.
However, in the case of "read", execbuiltin() blocks on the I/O, so
list_pipe remains true, and when the TSTP is received, update_job()
proceeds as if execpline() is going to fork.  

So the following hack does the right thing in the case of piping to
true where execbuiltin() has returned, but does not do the right thing
in the case of read.  What needs to be tested in place of (!list_pipe)
to determine that the tail of the current pipeline is a simple shell
builtin?

In fact even that may not be enough, maybe this needs to know if the
current job is a simple shell builtin -- it might be blocked on a
"while read; do ..." or on a "wait" in the middle of a loop, etc.

--- ../zsh-forge/current/Src/signals.c	2011-08-06 11:13:23.000000000 -0700
+++ Src/signals.c	2011-08-08 22:28:11.000000000 -0700
@@ -490,14 +490,20 @@
 	 * update it.
 	 */
 	if (findproc(pid, &jn, &pn, 0)) {
+	    if (!list_pipe && (jn->stat & STAT_CURSH) &&
+		WIFSTOPPED(status) && WSTOPSIG(status) == SIGTSTP) {
+		killjb(jn, SIGCONT);
+		zwarn("job can't be suspended");
+	    } else {
 #if defined(HAVE_WAIT3) && defined(HAVE_GETRUSAGE)
-	    struct timezone dummy_tz;
-	    gettimeofday(&pn->endtime, &dummy_tz);
-	    pn->status = status;
-	    pn->ti = ru;
+		struct timezone dummy_tz;
+		gettimeofday(&pn->endtime, &dummy_tz);
+		pn->status = status;
+		pn->ti = ru;
 #else
-	    update_process(pn, status);
+		update_process(pn, status);
 #endif
+	    }
 	    update_job(jn);
 	} else if (findproc(pid, &jn, &pn, 1)) {
 	    pn->status = status;


  reply	other threads:[~2011-08-09  6:10 UTC|newest]

Thread overview: 16+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2011-08-06  3:31 Bart Schaefer
2011-08-07 17:50 ` Peter Stephenson
2011-08-07 21:43   ` Bart Schaefer
2011-08-08  4:05     ` Bart Schaefer
2011-08-08 18:27       ` Peter Stephenson
2011-08-09  6:10         ` Bart Schaefer [this message]
2011-08-09 20:19           ` Peter Stephenson
2011-08-13 18:52             ` Bart Schaefer
2011-08-13 20:15               ` Bart Schaefer
2011-09-12 13:51               ` Alexey I. Froloff
2011-09-12 16:03                 ` Bart Schaefer
2011-09-12 16:18                   ` Bart Schaefer
2011-09-12 16:35                     ` Peter Stephenson
2011-09-15 14:57                       ` Alexey I. Froloff
2011-09-16 16:16                         ` Bart Schaefer
2011-09-12 16:27                   ` Alexey I. Froloff

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=110808231032.ZM2380@torch.brasslantern.com \
    --to=schaefer@brasslantern.com \
    --cc=zsh-workers@zsh.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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).