Zsh Mailing List Archive
Messages sorted by: Reverse Date, Date, Thread, Author

Re: long-standing tty related issue: wrapped Emacs not suspended



On Fri, Sep 21, 2018 at 9:57 AM, Peter Stephenson
<p.w.stephenson@xxxxxxxxxxxx> wrote:
> On Thu, 20 Sep 2018 14:30:05 +0200
> Vincent Lefevre <vincent@xxxxxxxxxx> wrote:
>> is suspended as expected. But when Emacs is wrapped in a function,
>> it is not suspended. After "zsh -f":
>>
>> zira% e() { emacs -nw "$@"; }
>> zira% e &
>>
>> I cannot quit Emacs or get the zsh prompt. I need to kill the
>> terminal.
>
> I think this one *is* the same basic issue that Thilo was talking about.

I think maybe you're mis-reading.  Note that in Vincent's case
backgrounding the function causes emacs to FAIL to stop (or so he
says), not to stop forever and need a SIGCONT.

When Vincent says:
>> I've tested the same thing with other shells: dash behaves like
>> zsh, and bash, ksh93 and mksh immediately terminate.

I'm fairly sure this is because bash, ksh93, and mksh are ignoring the
TTIN signal.  In that case the shell receives a read error on standard
input instead of being stopped, which causes those shells to exit.

Zsh and dash on the other hand allow the TTIN to stop the shell, which
deadlocks everything; either emacs is running but not paying attention
to the terminal because it is trying to be an X application, or it is
also stopped.

I have a vague recollection that this is an emacs-specific problem, in
that it actively attempts to grab control of the terminal and
sometimes succeeds (race with the parent shell?).

FWIW I can't get what Vincent describes to happen at all with the
above example and the current git checkout, even after assorted
bg/fg/^Z/etc.  But the system on which I can currently test doesn't
have an X-enabled emacs.

I *can* get both the shell and emacs to be suspended even though the
parent thinks they are running in the background, by starting the "e"
function in the foreground and then doing ^Z.

% jobs
[1]  - running    e
% ps x
  PID TTY      STAT   TIME COMMAND
21333 ?        S      0:00 sshd: barts@pts/5
21334 pts/5    Ss     0:00 Src/zsh
21446 pts/5    T      0:00 emacs -nw
21453 pts/5    T      0:00 Src/zsh
21569 pts/5    R+     0:00 ps x

At this point if I bring "e" into the foreground explicitly, the shell
ends up blocked:

% fg
fg: no current job
% jobs
[1]  - running    e
% fg %1
[1]  - running    e
(deadlock)

If next I "kill -CONT 21446", emacs briefly grabs the terminal, then
goes back to being stopped and the parent shell regains control.  It
still believes "e" is running.

If instead I "kill -CONT 21453", that subshell exits, the parent shell
gets back control and deletes the "e" job, and emacs is orphaned
(still stopped, and unable to continue).

> However, there are a couple of interesting zsh-specific issues here.
>
> The fact that another instance of the shell is created on the ^Z is
> actually a special feature for allowing you to suspend builtins,
> designed for functions and pipelines with more processing

Indeed, a potential problem is that emacs is a child of the parent
shell, not a child of the subshell spawned to suspend the "e"
function, so the subshell can't wait() for it.  The parent shell now
has to keep track of two jobs for the backgrounded function, and I
think it's losing track of one of them.

Also, the parent shell should probably be sending a SIGCONT to all
those jobs whenever they are fg'd, even if it believes they are
already running.  SIGCONT is harmless for a job that is not stopped,
and trusting the job table idea of the process state is an unnecessary
optimization.



Messages sorted by: Reverse Date, Date, Thread, Author