dtach -n always exits with -1 when the command exits
Closed this issue · 6 comments
When ever dtach exits because the command started by dtach finishes it always seems to exit with -1 when started in dtach -n mode.
For example,
strace -s 8192 -ff ./dtach -n /tmp/f /bin/sh -c "sleep 1"
Produces the following snipped output,
<... select resumed> ) = 1 (in [4])
--- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=14569, si_uid=1000, si_status=0, si_utime=0, si_stime=0} ---
rt_sigreturn({mask=[]}) = 1
read(4, 0x7ffdb1138830, 4096) = -1 EIO (Input/output error)
unlink("/tmp/f") = 0
exit_group(1) = ?
+++ exited with 1 +++
This patch works for me. Inspired from (https://bugs.python.org/file16863/io-openpty.patch). Is something like this acceptable ?
--- a/master.c
+++ b/master.c
@@ -253,8 +253,12 @@ pty_activity(int s)
len = read(the_pty.fd, buf, sizeof(buf));
/* Error -> die */
- if (len <= 0)
- exit(1);
+ if (len <= 0) {
+ if (len == -1 && errno == EIO)
+ exit(0);
+ else
+ exit(1);
+ }
Here is an expanded version of the patch which tries to save the exit code. See if it works for you:
--- a/dtach.h
+++ b/dtach.h
@@ -71,6 +71,7 @@
#include <sys/stat.h>
#include <sys/socket.h>
#include <sys/un.h>
+#include <sys/wait.h>
#ifndef S_ISREG
#define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
--- a/master.c
+++ b/master.c
@@ -28,6 +28,8 @@ struct pty
#endif
/* Process id of the child. */
pid_t pid;
+ /* Exit code of the child. */
+ int exit_code;
/* The terminal parameters of the pty. Old and new for comparision
** purposes. */
struct termios term;
@@ -72,6 +74,14 @@ die(int sig)
/* Well, the child died. */
if (sig == SIGCHLD)
{
+ int status;
+
+ if (waitpid(-1, &status, WNOHANG) > 0)
+ {
+ if (WIFEXITED(status))
+ the_pty.exit_code = WEXITSTATUS(status);
+ }
+
#ifdef BROKEN_MASTER
/* Damn you Solaris! */
close(the_pty.fd);
@@ -134,7 +144,7 @@ init_pty(char **argv, int statusfd)
printf("%s: could not execute %s: %s\r\n", progname,
*argv, strerror(errno));
fflush(stdout);
- _exit(127);
+ _exit(1);
}
/* Parent.. Finish up and return */
#ifdef BROKEN_MASTER
@@ -254,7 +264,17 @@ pty_activity(int s)
/* Error -> die */
if (len <= 0)
- exit(1);
+ {
+#ifdef EIO
+ if (len < 0 && errno == EIO)
+ len = 0;
+#endif
+
+ if (len == 0)
+ exit(the_pty.exit_code);
+ else
+ exit(1);
+ }
#ifdef BROKEN_MASTER
/* Get the current terminal settings. */
Any updates on this issue? Results in failure in systemd units when attempting to stop the service
I never received a reply from @hummerbliss saying whether my expanded version of the patch worked for them or not.
Maybe you could try it and see if there are any issues with it?
@crigler I tried it.
patched version: ~/resources/dtach/dtach
current version: /usr/bin/dtach
.
~
❯ ~/resources/dtach/dtach -N /tmp/a1 echo "ASD" && echo "success" || echo "failed"
success
~
❯ /usr/bin/dtach -N /tmp/a1 echo "ASD" && echo "success" || echo "failed"
failed
Also tried with a complex example with rtorrent. It works.
Also the OP's example works.
~
❯ strace -s 8192 -ff ~/resources/dtach/dtach -n /tmp/f /bin/sh -c "sleep 1" |& grep 'exited with'
[pid 12626] +++ exited with 0 +++
[pid 12628] +++ exited with 0 +++
+++ exited with 0 +++
~
❯ strace -s 8192 -ff /usr/bin/dtach -n /tmp/f /bin/sh -c "sleep 1" |& grep 'exited with'
[pid 12641] +++ exited with 0 +++
[pid 12643] +++ exited with 0 +++
+++ exited with 1 +++
However, I would like to ask does this have any bearing on what the executed command returns? Actually I checked with top after I did kill -9 <toppid>
The patched version outputs:
❯ ~/resources/dtach/dtach -N /tmp/a1 top
[1] 12274 killed ~/resources/dtach/dtach -N /tmp/a1 top
~ 7s
❯ echo $?
137
The same by the nonpatch version.
So I am assuming dtach transmits the executed commands error code.
Apologies for missing the updates. Works well for me.