zsh-workers
 help / color / mirror / code / Atom feed
From: Stephane Chazelas <stephane@chazelas.org>
To: Roman Perepelitsa <roman.perepelitsa@gmail.com>,
	Zsh hackers list <zsh-workers@zsh.org>
Subject: Re: Opening a file descriptor for reading with exec breaks vim shell
Date: Sun, 17 May 2020 10:03:48 +0100	[thread overview]
Message-ID: <20200517090348.2lomdks3fpmxl433@chazelas.org> (raw)
In-Reply-To: <CAN=4vMrBH1RhJTNNHWkqCuri+Z8W-YtdGrWmb1d3H0geNAU6DQ@mail.gmail.com>

2020-05-15 06:57:10 +0200, Roman Perepelitsa:
[...]
> Reproduce:
> 
>   adam% vim
>   :shell
>   adam% exec {fd}</dev/null
>   adam% exit
>   zsh: suspended (tty output)  vim
[...]

Can be reproduced with:

~$ sh -c 'zsh -f; read x'
% exec {fd}</dev/null
% exit
zsh: suspended (tty input)  sh -c 'zsh -f; read x'

Also happens if you run set +m -m in that zsh.

What happens is that here zsh is not a group leader on startup
so creates a new process group and makes it the forground job.

It normally restores the foreground group upon exit, but when
running those exec or set -m commands, that doesn't happen.

That is because in those cases, the origpgrp variable (which
records the original process group to be restored on exit) is
being incorrectly overridden. In the case of "exec {fd}<",
because init_io is being called by mistake.

Note that in any case, and with any shell with job control
support, you get the same problem if you run kill -s KILL "$$"
in that shell.

The patch below fixes those, but I have to admit there's a lot
of the related code in zsh I don't understand, a lot of the
behaviour I don't understand either. It's possible that patch
could break things related to clone, zpty, set -m or opening tty
devices, but it seems to me that some of that is already quite
broken.

For instance, set -m doesn't seem to work (or at least do
anything useful). In  non-interactive shells, it  does seem to
cause jobs to be put in their own process groups, but not them
being put in foreground/background of the controlling terminal
so it's not really "job control" (as the doc says).

In interactive shells started with zsh +m, set -m doesn't seem
to be usable (causes lock ups probably caused by some SIGTTIN),
regardless of whether zsh is started as session, group leader or
not.

I also tried starting an interactive zsh +m with no controlling
terminal (but still with I/O to one so I could enter commands)
as a session leader, then do a exec <> some-tty >&0 2>&0 (where
some-tty had no controlling session). That did not attach that
terminal to zsh's session (I suppose because <> calls open()
with O_NOCTTY, same with sysopen), and set -m had no effect
(monitor option remained off).

diff --git a/Src/exec.c b/Src/exec.c
index 2b8e2167f..5bd317880 100644
--- a/Src/exec.c
+++ b/Src/exec.c
@@ -3669,7 +3669,7 @@ execcmd_exec(Estate state, Execcmd_params eparams,
 		addfd(forked, save, mfds, fn->fd1, fil, 0, fn->varid);
 		/* If this is 'exec < file', read from stdin, *
 		 * not terminal, unless `file' is a terminal. */
-		if (nullexec == 1 && fn->fd1 == 0 &&
+		if (nullexec == 1 && fn->fd1 == 0 && !fn->varid &&
 		    isset(SHINSTDIN) && interact && !zleactive)
 		    init_io(NULL);
 		break;
diff --git a/Src/init.c b/Src/init.c
index 3d6c94d04..342f0a697 100644
--- a/Src/init.c
+++ b/Src/init.c
@@ -697,11 +697,14 @@ init_io(char *cmd)
      * process group leader.
      */
     mypid = (zlong)getpid();
-    if (opts[MONITOR] && (SHTTY != -1)) {
-	origpgrp = GETPGRP();
-        acquire_pgrp(); /* might also clear opts[MONITOR] */
-    } else
-	opts[MONITOR] = 0;
+    if (opts[MONITOR]) {
+	if (SHTTY == -1)
+	    opts[MONITOR] = 0;
+	else if (!origpgrp) {
+	    origpgrp = GETPGRP();
+	    acquire_pgrp(); /* might also clear opts[MONITOR] */
+	}
+    }
 #else
     opts[MONITOR] = 0;
 #endif
diff --git a/Src/options.c b/Src/options.c
index 7586d21d2..cf3664218 100644
--- a/Src/options.c
+++ b/Src/options.c
@@ -878,11 +878,12 @@ dosetopt(int optno, int value, int force, char *new_opts)
     } else if (!force && optno == MONITOR && value) {
 	if (new_opts[optno] == value)
 	    return 0;
-	if (SHTTY != -1) {
+	if (SHTTY == -1)
+	    return -1;
+	if (!origpgrp) {
 	    origpgrp = GETPGRP();
 	    acquire_pgrp();
-	} else
-	    return -1;
+	}
 #else
     } else if(optno == MONITOR && value) {
 	    return -1;

  reply	other threads:[~2020-05-17  9:04 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-05-15  4:57 Roman Perepelitsa
2020-05-17  9:03 ` Stephane Chazelas [this message]
2020-05-18  8:35   ` Roman Perepelitsa
2020-05-19 17:31   ` Peter Stephenson

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=20200517090348.2lomdks3fpmxl433@chazelas.org \
    --to=stephane@chazelas.org \
    --cc=roman.perepelitsa@gmail.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).