Peter Whaite writes: > Philippe Troin said: > > Philippe Troin writes: > > > > > I'll check out how the other shells (bash and tcsh) handle this case > > > and will post a patch for bin_suspend() later. > > > > I was looking at bash, and they do not do anything special (like > > reverting to the original pgrp) before suspending. > > > > Can you try su'ing with bash? I was able to get it stuck with my local > > test program here... but I do not have GNU su installed (yet). > > Looks like bash can deal with GNU su. So can tcsh. > > % su --shell=/bin/bash peta > Password: > [peta@aragorn zsh]$ suspend > zsh: suspended (signal) /bin/su --shell=/bin/bash peta > 1 % fg > [1] + continued /bin/su --shell=/bin/bash peta > > 11779 11790 11790 11790 pts/2 12959 S 501 0:00 \_ -zsh > 11790 12894 12894 11790 pts/2 12959 S 0 0:00 \_ /bin/su --shell=/bin/bash peta > 12894 12903 12903 11790 pts/2 12959 S 501 0:00 \_ bash > 12903 12959 12959 11790 pts/2 12959 R 501 0:00 \_ ps xajfw Mrm, that's not GNU su. Or it's a very heavily patched version of GNU su. I've check shellutils 2.0 and it does a straight exec(), and does not leave a parent process like seen above... So I cannot reproduce your exact problem, but I think I've fixed it nevertheless... Can you try the enclosed patch? It's against the latest CVS, but it applies with a little bit of fuzz to 4.1.0-dev-7. Here is a transcript of a session which shows that it works. "spawn" is a very simple program that does what I believe your version of su does. Replace it with "su --shell=/path/to/zsh". phil@ceramic:~/y% ./spawn zsh/Src/zsh phil@ceramic:~/y[2]% suspend zsh: 13283 suspended ./spawn zsh/Src/zsh phil@ceramic:~/y% bg [1] + continued ./spawn zsh/Src/zsh phil@ceramic:~/y% [1] + 13283 suspended (tty input) ./spawn zsh/Src/zsh phil@ceramic:~/y% fg [1] + continued ./spawn zsh/Src/zsh phil@ceramic:~/y[2]% exec zsh/Src/zsh phil@ceramic:~/y[2]% suspend zsh: 13283 suspended ./spawn zsh/Src/zsh zsh: exit 20 phil@ceramic:~/y% bg [1] + continued ./spawn zsh/Src/zsh phil@ceramic:~/y% [1] + 13283 suspended (tty input) ./spawn zsh/Src/zsh phil@ceramic:~/y% fg [1] + continued ./spawn zsh/Src/zsh phil@ceramic:~/y[2]% exit child exited with status 0 phil@ceramic:~/y% You'll notice that: - suspend now works. - suspend STILL works across exec (nice touch) - bg'ing or resuming reports "suspended (tty input)" correctly, without the 1 second delay anymore. Technical explanation: - zsh-workers/17859 makes the case why we always want to have interactive zsh instances to be the leader of their process group, so I won't come back to this. - zsh-workers/17859 created a new process group if zsh was started interactively without being a process group leader. This happens frequently we have have this typical process hierarchy: zsh \_ program running system("zsh") (eg. mail, dpkg, your su) \_ zsh The fix consists in the following: - when the user invokes "suspend", and we created our own process group, we must go back to the process group we came from and send a SIGTSTP to the whole process group. When the process is resumed, it will reacquire its process group leader status. - also, when we run "exec somecommand", we must restore the original process group. Patch walk-through: - introduced a new global variable, origpgrp, containing the initial process group. It is only set in init_io(). - moved the process group acquiring and terminal acquiring code from init_io() to a new function, acquire_pgrp() in jobs.c. init_io() now calls acquire_pgrp(). - created a new function in jobs.c, release_pgrp() that gives the terminal foreground process group back to origprgp and moves back zsh to this process group. - in bin_suspend(): before suspending, call release_pgrp(). Use killpg() to broadcast the signal to the whole process group, rather than just kill()ing ourselves (note: in most cases it's the same since zsh is alone in its process group, however in the above case where zsh is spawned by another process, the spawning process must also receive SIGTSTP, just as if CTRL-Z had been pressed). After zsh is resumed call acquire_pgrp() again which will (maybe) move back zsh to its own process group, and handle the terminal in the proper way (rather than playing tricks with sleep()). - in exec.c: we want to be sure that if zsh has moved to its own process group, it moves back to its original process group before exec'ing a final command. I had to add an extra parameter to entersubsh() indicating whether or not reverting to an eventual origpgrp is needed. It is always zero, except when called from execsubst(). Note to Bart: at the stage where entersubsh() is called from execsubst(), the condition seems to be: (do_exec || (type >= WC_CURSH && last1 == 1)) && !forked You said that do_exec && !forked was sufficient, but do_exec is set to 1 two lines down if (type >= WC_CURSH && last1 == 1). Also, inside entersubsh(), where release_pgrp() is called, I have to check that (getpid() == mypgrp) in addition to revertpgrp being true. Otherwise some temporary zsh subprocesses (like the ones created during a pipe before they exec the actual executables) will wrongly revert their process group. I've also enclosed the trivial "spawn" program, in case you don't have the RH shellutils. And you might want to try it with other shells. I believe zsh is the only shell that implements terminal handling properly now: bash fails to suspend correctly with spawn, and tcsh gets lost after it execs itself. Peter, can you confirm that this patch makes zsh perform as expected with your su? If yes, then Bart, would you consider it for inclusion? Phil.