zsh-workers
 help / color / mirror / code / Atom feed
From: Peter Stephenson <p.w.stephenson@ntlworld.com>
To: zsh-workers@zsh.org
Subject: Re: Bug in ZSH 5.0.0 - Segmentation fault after sending process to background
Date: Thu, 11 Oct 2012 15:35:50 +0100	[thread overview]
Message-ID: <CAECNH1TC6yo8L_WAwTU2KHLDPYuiyEh_=RG6s_YKaKKj+7sObQ@mail.gmail.com> (raw)
In-Reply-To: <5076CDC9.9040908@googlemail.com>

On 11 October 2012 14:46, BlueC0re <bluecore90@googlemail.com> wrote:
> zsh version 5.0.0 crashes with a segfault if you have a custom precmd
> specified (containing an additional command block), and sending a
> process to the background.

Yes, it does.  Thanks for the reproduction information.

That's bad, right?

I think I understand much of this.  Certain very simple commands are
optimised to be run by execsimple(), bypassing job control, so "thisjob"
won't be set up the way you expect.  This causes the observed mayhem if
the code actually does look at job control.

I've added some tests to ensure thisjob is valid where necessary, and
also ensured that it's not valid for code called from execsimple(),
since it's never been set up --- or if it has we have no reason to
suppose it's a job we're interested in.  While I can't guarantee
invalidating thisjob in execsimple is harmless, the case here suggests
that if it causes anything else that's probably something we want to
find out about rather than sweeping under the carpet.

Using my own initialisation files I can see an execshfunc() being called
from execsimple().  This doesn't strike me as being particularly
"simple", although execsimple says the requirement is the code runs
entirely within the shell, which is true (code run from the function
that doesn't will cause its own jobs to be created).

The change in hasprocs() is just there to make debugging a little
easier.

Index: Src/exec.c
===================================================================
RCS file: /cvsroot/zsh/zsh/Src/exec.c,v
retrieving revision 1.212
diff -p -u -r1.212 exec.c
--- Src/exec.c	7 Oct 2012 19:46:46 -0000	1.212
+++ Src/exec.c	11 Oct 2012 14:19:34 -0000
@@ -404,7 +404,17 @@ execcursh(Estate state, int do_exec)
     /* Skip word only used for try/always */
     state->pc++;

-    if (!list_pipe && thisjob != list_pipe_job && !hasprocs(thisjob))
+    /*
+     * The test thisjob != -1 was added because sometimes thisjob
+     * can be invalid at this point.  The case in question was
+     * in a precmd function after operations involving background
+     * jobs.
+     *
+     * This is because sometimes we bypass job control to execute
+     * very simple functions via execssimple().
+     */
+    if (!list_pipe && thisjob != -1 && thisjob != list_pipe_job &&
+	!hasprocs(thisjob))
 	deletejob(jobtab + thisjob, 0);
     cmdpush(CS_CURSH);
     execlist(state, 1, do_exec);
@@ -1064,7 +1074,7 @@ static int
 execsimple(Estate state)
 {
     wordcode code = *state->pc++;
-    int lv;
+    int lv, otj;

     if (errflag)
 	return (lastval = 1);
@@ -1075,6 +1085,13 @@ execsimple(Estate state)

     code = wc_code(*state->pc++);

+    /*
+     * Because we're bypassing job control, ensure the called
+     * code doesn't see the current job.
+     */
+    otj = thisjob;
+    thisjob = -1;
+
     if (code == WC_ASSIGN) {
 	cmdoutval = 0;
 	addvars(state, state->pc - 1, 0);
@@ -1086,6 +1103,8 @@ execsimple(Estate state)
     } else
 	lv = (execfuncs[code - WC_CURSH])(state, 0);

+    thisjob = otj;
+
     return lastval = lv;
 }

@@ -4313,7 +4332,9 @@ execshfunc(Shfunc shf, LinkList args)
     if (errflag)
 	return;

-    if (!list_pipe && thisjob != list_pipe_job && !hasprocs(thisjob)) {
+    /* thisjob may be invalid if we're called via execsimple: see execcursh */
+    if (!list_pipe && thisjob != -1 && thisjob != list_pipe_job &&
+	!hasprocs(thisjob)) {
 	/* Without this deletejob the process table *
 	 * would be filled by a recursive function. */
 	last_file_list = jobtab[thisjob].filelist;
Index: Src/jobs.c
===================================================================
RCS file: /cvsroot/zsh/zsh/Src/jobs.c,v
retrieving revision 1.91
diff -p -u -r1.91 jobs.c
--- Src/jobs.c	21 Sep 2012 12:45:29 -0000	1.91
+++ Src/jobs.c	11 Oct 2012 14:19:34 -0000
@@ -209,7 +209,13 @@ findproc(pid_t pid, Job *jptr, Process *
 int
 hasprocs(int job)
 {
-    Job jn = jobtab + job;
+    Job jn;
+
+    if (job < 0) {
+	DPUTS(1, "job number invalid in hasprocs");
+	return 0;
+    }
+    jn = jobtab + job;

     return jn->procs || jn->auxprocs;
 }

pws


  reply	other threads:[~2012-10-11 14:36 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2012-10-11 13:46 BlueC0re
2012-10-11 14:35 ` Peter Stephenson [this message]
2012-10-11 15:52   ` Bart Schaefer

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='CAECNH1TC6yo8L_WAwTU2KHLDPYuiyEh_=RG6s_YKaKKj+7sObQ@mail.gmail.com' \
    --to=p.w.stephenson@ntlworld.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).