zsh-workers
 help / color / mirror / code / Atom feed
* Re: PATCH: loop killing
  1999-06-24  9:08 PATCH: loop killing Sven Wischnowsky
@ 1999-06-24  9:00 ` Peter Stephenson
  1999-06-25 13:21 ` Andrej Borsenkow
  1 sibling, 0 replies; 8+ messages in thread
From: Peter Stephenson @ 1999-06-24  9:00 UTC (permalink / raw)
  To: zsh-workers

Sven Wischnowsky wrote:
> This is the solution which executes commands in a loop in the same
> process group as the parent shell.

This seems to be the neatest solution, covering most of the common things
you want to do without any fuss.  But at the moment something nasty is
happening with shell functions.

% fn() { less $*; }
% fn glob.c
^Z
<job disappears completely>

If I type a few characters before hitting ^Z, then I get the `suspended'
message, and the `continued' message when I type fg, but then the job
immediately disappears again.

Hmmm, that didn't seem to be working properly even before, except the
problem then was that when I tried to continue it I got the message 
  zsh: 39221 suspended (tty output)  l glob.c
so it looks like the process groups were already getting messed up.
So maybe the new problem is just the old one appearing in a different
place.

-- 
Peter Stephenson <pws@ibmth.df.unipi.it>       Tel: +39 050 844536
WWW:  http://www.ifh.de/~pws/
Dipartimento di Fisica, Via Buonarroti 2, 56127 Pisa, Italy


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

* PATCH: loop killing
@ 1999-06-24  9:08 Sven Wischnowsky
  1999-06-24  9:00 ` Peter Stephenson
  1999-06-25 13:21 ` Andrej Borsenkow
  0 siblings, 2 replies; 8+ messages in thread
From: Sven Wischnowsky @ 1999-06-24  9:08 UTC (permalink / raw)
  To: zsh-workers


This is the solution which executes commands in a loop in the same
process group as the parent shell. I.e. ^C'ing loops such as

  while true; do zcat ...; done

works now, even with ill-behaved progrms such as zcat. But of course I 
could think of a case where we still have problems with such programs:

  zcat ... | while true; do zcat ...; done

Here we need two ^C's to interrupt the whole thing. The first one
interrupts both zcats currently running, but since none of them tells
us that it was interrupted the loop happily continues running. But
every zcat started in it after the first ^C finds out that the group
leader is finished and puts itself in the process group of the shell
and thus the shell sees the second ^C.
Again, two possible ways to solve this are: 1) do all job control by
hand -- merely thinking about this causes me pain, 2) these dummy
processes I was talking about. I half-heartedly had a look at 2) and
couldn't get it to work immediatly and then stopped trying. Especially 
since Bart and I don't like this anyway and, after all, this is a
different case because we *can* stop such a loop -- we only need two
^C's. And what the heck... at least we are much better than bash.

This also fixes another problem with loops, namely:

  foo | while true; do bar; done

...where bar was finishing very quickly. In that case the code didn't
find out that it had to suspend because it never looked at the state
of the super-job (foo).


Bye
 Sven

diff -u oos/exec.c Src/exec.c
--- oos/exec.c	Thu Jun 24 08:55:15 1999
+++ Src/exec.c	Thu Jun 24 10:47:16 1999
@@ -933,7 +933,10 @@
 		    lastval2 & 0200)
 		    killpg(mypgrp, lastval2 & ~0200);
 		if ((list_pipe || last1 || pline_level) &&
-		    !list_pipe_child && jn->stat & STAT_STOPPED) {
+		    !list_pipe_child && 
+		    ((jn->stat & STAT_STOPPED) ||
+		     (list_pipe_job && pline_level &&
+		      (jobtab[list_pipe_job].stat & STAT_STOPPED)))) {
 		    pid_t pid;
 		    int synch[2];
 
@@ -959,10 +962,14 @@
 			close(synch[1]);
 			read(synch[0], &dummy, 1);
 			close(synch[0]);
-			jobtab[list_pipe_job].other = newjob;
-			jobtab[list_pipe_job].stat |= STAT_SUPERJOB;
-			jn->stat |= STAT_SUBJOB | STAT_NOPRINT;
-			jn->other = pid;
+			/* If this job has finished, we turn this into a
+			 * normal (non-super-) job. */
+			if (!(jn->stat & STAT_DONE)) {
+			    jobtab[list_pipe_job].other = newjob;
+			    jobtab[list_pipe_job].stat |= STAT_SUPERJOB;
+			    jn->stat |= STAT_SUBJOB | STAT_NOPRINT;
+			    jn->other = pid;
+			}
 			if (list_pipe || last1)
 			    killpg(jobtab[list_pipe_job].gleader, SIGSTOP);
 			break;
@@ -2196,8 +2203,9 @@
 		    attachtty(jobtab[thisjob].gleader);
 	    }
 	}
-	else if (!jobtab[thisjob].gleader ||
-		 (setpgrp(0L, jobtab[thisjob].gleader) == -1)) {
+	else if (!(list_pipe || list_pipe_child || pline_level > 1) &&
+		 (!jobtab[thisjob].gleader ||
+		  setpgrp(0L, jobtab[thisjob].gleader) == -1)) {
 	    jobtab[thisjob].gleader = getpid();
 	    if (list_pipe_job != thisjob &&
 		!jobtab[list_pipe_job].gleader)
diff -u oos/jobs.c Src/jobs.c
--- oos/jobs.c	Thu Jun 24 08:55:16 1999
+++ Src/jobs.c	Thu Jun 24 10:56:48 1999
@@ -185,8 +185,9 @@
 
 		for (i = 1; i < MAXJOB; i++)
 		    if ((jobtab[i].stat & STAT_SUPERJOB) &&
-			jobtab[i].other == job) {
-			killpg(jobtab[i].gleader, SIGSTOP);
+			jobtab[i].other == job &&
+			jobtab[i].gleader) {
+			killpg(jobtab[i].gleader, SIGTSTP);
 			break;
 		    }
 	    }
diff -u oos/signals.c Src/signals.c
--- oos/signals.c	Thu Jun 24 08:55:18 1999
+++ Src/signals.c	Thu Jun 24 10:57:16 1999
@@ -584,7 +584,7 @@
                 for (pn = jobtab[jn->other].procs; pn; pn = pn->next)
                     kill(pn->pid, sig);
  
-                for (pn = jn->procs; pn->next; pn = pn->next)
+                for (pn = jn->procs; pn; pn = pn->next)
                     err = kill(pn->pid, sig);
  
                 return err;

--
Sven Wischnowsky                         wischnow@informatik.hu-berlin.de


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

* RE: PATCH: loop killing
  1999-06-24  9:08 PATCH: loop killing Sven Wischnowsky
  1999-06-24  9:00 ` Peter Stephenson
@ 1999-06-25 13:21 ` Andrej Borsenkow
  1 sibling, 0 replies; 8+ messages in thread
From: Andrej Borsenkow @ 1999-06-25 13:21 UTC (permalink / raw)
  To: Sven Wischnowsky, zsh-workers

>
>   zcat ... | while true; do zcat ...; done
>
> Here we need two ^C's to interrupt the whole thing.

I just tried it (zcat | while true; do zcat ; done) and it stops at the first
^C. May be, there are subtleties I miss or it has something to do with the last
process group patch.

Well done, really!

Ooops! Just found something weird:

bor@itsrm2:~%> zcat | while true
do
zcat
done
Now press ^\ (QUIT)
bor@itsrm2:~%>

??? QUIT is supposed to give you core ... Once more:

bor@itsrm2:~%> zcat | while true
do
zcat
done
^Zzsh: suspended  zcat | while true; do; zcat; done
bor@itsrm2:~%> fg
[13]  - continued  zcat | while true; do; zcat; done
^\zsh: quit (core dumped)  zcat | while true; do; zcat; done

(note, that I have noticeable delay between ^\ and core dumped message ... but,
may be, it is related to wrinting core ...)

It is even worse

bor@itsrm2:~%> while true
do
zcat
done
^Z^Z^Z^Z^Z^Z^Z

Nothing happens at all.

/andrej

This is with all but the last patch of Peter (typeset -g).


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

* Re: PATCH: loop killing
  1999-06-25 16:23   ` Andrej Borsenkow
@ 1999-06-25 16:29     ` Peter Stephenson
  0 siblings, 0 replies; 8+ messages in thread
From: Peter Stephenson @ 1999-06-25 16:29 UTC (permalink / raw)
  To: Zsh hackers list

"Andrej Borsenkow" wrote:
> Now, is it my system bug? Any idea?

I'm getting exactly the same thing with AIX 3.2:  if the process is
the immediate child of an xterm, it won't suspend, if it's a subshell, it
will.  I won't be able to try it anywhere else until I've got pws-24
sorted out.

pws


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

* RE: PATCH: loop killing
  1999-06-25 15:00 ` Andrej Borsenkow
@ 1999-06-25 16:23   ` Andrej Borsenkow
  1999-06-25 16:29     ` Peter Stephenson
  0 siblings, 1 reply; 8+ messages in thread
From: Andrej Borsenkow @ 1999-06-25 16:23 UTC (permalink / raw)
  To: Andrej Borsenkow, Sven Wischnowsky, zsh-workers

>
> The only difference, that I currently can see, is, that when it does not work,
> zsh is session leader:

Well, it does work with csh (that starts programs in seperate program group) and
does not work with ksh (that starts porgrams in it's own program group). It does
work if program is started alone and not as part of loop. Note the difference
(this is ksh, but the same is true for zsh):

This is for while true; zcat; done case:

bor@itsrm2:/tools/src/zsh-3.1.5-pws-23%> ps -jt pts/12
   PID  PGID   SID TTY      TIME CMD
  9064  9002  9002 pts/12   0:00 zcat
  9002  9002  9002 pts/12   0:00 ksh

And this is for the simple zcat case:

bor@itsrm2:/tools/src/zsh-3.1.5-pws-23%> ps -jt pts/12
   PID  PGID   SID TTY      TIME CMD
  9072  9072  9002 pts/12   0:00 zcat
  9002  9002  9002 pts/12   0:00 ksh

In the first case job PGID == SID and ^Z does not work (zcat gets TSTP but
[zk]sh never gets SIGCLD). In the second case job PGID != SID and all works like
a charm

Now, is it my system bug? Any idea?

/andrej


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

* RE: PATCH: loop killing
  1999-06-25 14:21 Sven Wischnowsky
@ 1999-06-25 15:00 ` Andrej Borsenkow
  1999-06-25 16:23   ` Andrej Borsenkow
  0 siblings, 1 reply; 8+ messages in thread
From: Andrej Borsenkow @ 1999-06-25 15:00 UTC (permalink / raw)
  To: Sven Wischnowsky, zsh-workers

>
> > It is even worse
> >
> > bor@itsrm2:~%> while true
> > do
> > zcat
> > done
> > ^Z^Z^Z^Z^Z^Z^Z
> >
> > Nothing happens at all.
>
> This works for me.
>

It works for me for zsh with SHLVL > 1 :

bor@itsrm2:~%> echo $SHLVL
1
bor@itsrm2:~%> zsh
bor@itsrm2:~%> while true
while> do
while> zcat
while> done
^Zzsh: suspended  while true; do; zcat; done
bor@itsrm2:~%> echo $SHLVL
2
bor@itsrm2:~%> exit
bor@itsrm2:~%> echo $SHLVL
1
bor@itsrm2:~%> ps
   PID TTY      TIME CMD
  4598 pts/5    0:01 zsh
bor@itsrm2:~%>

Note, that no notification "you have stopped jobs" appear. But

bor@itsrm2:~%> zcat
^Z
zsh: suspended  zcat
bor@itsrm2:~%> exit
zsh: you have suspended jobs.
bor@itsrm2:~%> echo $SHLVL
1

Something is fishy. The same happens for me either under dtterm or xterm or in
telnet login zsh. dtterm and zsh run in different process groups.

The only difference, that I currently can see, is, that when it does not work,
zsh is session leader:

bor@itsrm2:~%> ps -j
   PID  PGID   SID TTY      TIME CMD
  4598  4598  4598 pts/5    0:02 zsh

but

bor@itsrm2:~%> zsh
bor@itsrm2:~%> ps -j
   PID  PGID   SID TTY      TIME CMD
  4598  4598  4598 pts/5    0:03 zsh
  6897  6897  4598 pts/5    0:00 zsh
bor@itsrm2:~%>


For some reason, in the first case Zsh does not get SIGCHLD (or is ignoring it)
and does not know that child was stopped.

/andrej


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

* RE: PATCH: loop killing
@ 1999-06-25 14:21 Sven Wischnowsky
  1999-06-25 15:00 ` Andrej Borsenkow
  0 siblings, 1 reply; 8+ messages in thread
From: Sven Wischnowsky @ 1999-06-25 14:21 UTC (permalink / raw)
  To: zsh-workers


Andrej Borsenkow wrote:

> Ooops! Just found something weird:
> 
> bor@itsrm2:~%> zcat | while true
> do
> zcat
> done
> Now press ^\ (QUIT)
> bor@itsrm2:~%>
> 
> ??? QUIT is supposed to give you core ... Once more:

For me it does, it just doesn't print that it has. I can't find the
right place where to stick the needle just now, I'll look at it over
the weekend.

> It is even worse
> 
> bor@itsrm2:~%> while true
> do
> zcat
> done
> ^Z^Z^Z^Z^Z^Z^Z
> 
> Nothing happens at all.

This works for me.

Bye
 Sven


--
Sven Wischnowsky                         wischnow@informatik.hu-berlin.de


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

* Re: PATCH: loop killing
@ 1999-06-24 11:55 Sven Wischnowsky
  0 siblings, 0 replies; 8+ messages in thread
From: Sven Wischnowsky @ 1999-06-24 11:55 UTC (permalink / raw)
  To: zsh-workers


Peter Stephenson wrote:

> Sven Wischnowsky wrote:
> > This is the solution which executes commands in a loop in the same
> > process group as the parent shell.
> 
> This seems to be the neatest solution, covering most of the common things
> you want to do without any fuss.  But at the moment something nasty is
> happening with shell functions.
> 
> % fn() { less $*; }
> % fn glob.c
> ^Z
> <job disappears completely>

execshfunc() deleted the job before the function was executed,
stealing us the information about it. I'm not too sure about the test
I changed this to... (but it seems to work).

> Hmmm, that didn't seem to be working properly even before, except the
> problem then was that when I tried to continue it I got the message 
>   zsh: 39221 suspended (tty output)  l glob.c
> so it looks like the process groups were already getting messed up.
> So maybe the new problem is just the old one appearing in a different
> place.

Right. The sub-shell for the shell (the super-job) put itself
unconditionally into the group of the gleader of the list_pipe_job --
but in cases like this one the sub-shell itself is the first job that
is entered into it, so gleader wasn't set and the sub-shell ended in
its own little process group which gave us the problem above when the
parent shell tried to foreground the job and used gleader of the
super-job for that.

Bye
 Sven

diff -u os/exec.c Src/exec.c
--- os/exec.c	Thu Jun 24 11:47:25 1999
+++ Src/exec.c	Thu Jun 24 13:40:28 1999
@@ -901,6 +901,9 @@
 		    DPUTS(!list_pipe_pid, "invalid list_pipe_pid");
 		    addproc(list_pipe_pid, list_pipe_text);
 
+		    if (!jn->procs->next)
+			jn->gleader = mypgrp;
+
 		    for (pn = jobtab[jn->other].procs; pn; pn = pn->next)
 			if (WIFSTOPPED(pn->status))
 			    break;
@@ -977,11 +980,13 @@
 		    else {
 			close(synch[0]);
 			entersubsh(Z_ASYNC, 0, 0);
-			setpgrp(0L, mypgrp = jobtab[list_pipe_job].gleader);
+			if (jobtab[list_pipe_job].procs)
+			    setpgrp(0L, mypgrp = jobtab[list_pipe_job].gleader);
 			close(synch[1]);
 			kill(getpid(), SIGSTOP);
 			list_pipe = 0;
 			list_pipe_child = 1;
+			opts[INTERACTIVE] = 0;
 			break;
 		    }
 		}
@@ -2793,14 +2798,13 @@
     if (errflag)
 	return;
 
-    if (!list_pipe) {
+    if (!list_pipe && thisjob != list_pipe_job) {
 	/* Without this deletejob the process table *
 	 * would be filled by a recursive function. */
 	last_file_list = jobtab[thisjob].filelist;
 	jobtab[thisjob].filelist = NULL;
 	deletejob(jobtab + thisjob);
     }
-
     if (isset(XTRACE)) {
 	LinkNode lptr;
 	printprompt4();
diff -u os/signals.c Src/signals.c
--- os/signals.c	Thu Jun 24 11:47:28 1999
+++ Src/signals.c	Thu Jun 24 13:44:36 1999
@@ -584,7 +584,7 @@
                 for (pn = jobtab[jn->other].procs; pn; pn = pn->next)
                     kill(pn->pid, sig);
  
-                for (pn = jn->procs; pn; pn = pn->next)
+                for (pn = jn->procs; pn->next; pn = pn->next)
                     err = kill(pn->pid, sig);
  
                 return err;

--
Sven Wischnowsky                         wischnow@informatik.hu-berlin.de


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

end of thread, other threads:[~1999-06-25 16:29 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
1999-06-24  9:08 PATCH: loop killing Sven Wischnowsky
1999-06-24  9:00 ` Peter Stephenson
1999-06-25 13:21 ` Andrej Borsenkow
1999-06-24 11:55 Sven Wischnowsky
1999-06-25 14:21 Sven Wischnowsky
1999-06-25 15:00 ` Andrej Borsenkow
1999-06-25 16:23   ` Andrej Borsenkow
1999-06-25 16:29     ` Peter Stephenson

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).