* 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
* 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-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 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
* 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 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
* RE: PATCH: loop killing
1999-06-24 9:08 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
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 11:55 PATCH: loop killing Sven Wischnowsky
-- strict thread matches above, loose matches on Subject: below --
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
1999-06-24 9:08 Sven Wischnowsky
1999-06-24 9:00 ` Peter Stephenson
1999-06-25 13:21 ` Andrej Borsenkow
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).