[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Bug#1052451: when receiving a SIGINT, unison should send it to the process group, not just to ssh



Control: reassign -1 unison-2.53 2.53.3-2
Control: retitle -1 when receiving a SIGINT, unison should send it to the process group, not just to ssh

A summary of the issue: I'm using a wrapper to ssh in order to
call ssh-add before the real ssh, when needed. When I run unison
and type Ctrl-C when a passphrase is asked by ssh-add, this kills
unison and my wrapper, but not ssh-add.

BTW, I've noticed that with svn (which uses my ssh wrapper in the
same way as unison), everything is OK. So this issue is specific
to the execution via unison.

In my wrapper, I've replaced "ssh-add" by "strace -o ~/str.out ssh-add",
so that I can now see more about the issue: with svn, ssh-add receives
the SIGINT, but not with unison!

In the ssh-add strace output when using svn:

[...]
openat(AT_FDCWD, "/dev/tty", O_RDWR)    = 4
ioctl(4, TCGETS, {c_iflag=ICRNL|IUTF8, c_oflag=NL0|CR0|TAB0|BS0|VT0|FF0|OPOST|ONLCR, c_cflag=B38400|CS8|CREAD, c_lflag=ISIG|ICANON|ECHO|ECHOE|ECHOK|IEXTEN|ECHOCTL|ECHOKE, ...}) = 0
ioctl(4, TCGETS, {c_iflag=ICRNL|IUTF8, c_oflag=NL0|CR0|TAB0|BS0|VT0|FF0|OPOST|ONLCR, c_cflag=B38400|CS8|CREAD, c_lflag=ISIG|ICANON|ECHO|ECHOE|ECHOK|IEXTEN|ECHOCTL|ECHOKE, ...}) = 0
ioctl(4, TCSETSF, {c_iflag=ICRNL|IUTF8, c_oflag=NL0|CR0|TAB0|BS0|VT0|FF0|OPOST|ONLCR, c_cflag=B38400|CS8|CREAD, c_lflag=ISIG|ICANON|ECHOE|ECHOK|IEXTEN|ECHOCTL|ECHOKE, ...}) = 0
ioctl(4, TCGETS, {c_iflag=ICRNL|IUTF8, c_oflag=NL0|CR0|TAB0|BS0|VT0|FF0|OPOST|ONLCR, c_cflag=B38400|CS8|CREAD, c_lflag=ISIG|ICANON|ECHOE|ECHOK|IEXTEN|ECHOCTL|ECHOKE, ...}) = 0
rt_sigaction(SIGALRM, {sa_handler=0x55993f0238b0, sa_mask=[], sa_flags=SA_RESTORER, sa_restorer=0x7f305625a510}, {sa_handler=SIG_DFL, sa_mask=[], sa_flags=0}, 8) = 0
rt_sigaction(SIGHUP, {sa_handler=0x55993f0238b0, sa_mask=[], sa_flags=SA_RESTORER, sa_restorer=0x7f305625a510}, {sa_handler=SIG_DFL, sa_mask=[], sa_flags=0}, 8) = 0
rt_sigaction(SIGINT, {sa_handler=0x55993f0238b0, sa_mask=[], sa_flags=SA_RESTORER, sa_restorer=0x7f305625a510}, {sa_handler=SIG_DFL, sa_mask=[], sa_flags=0}, 8) = 0
rt_sigaction(SIGPIPE, {sa_handler=0x55993f0238b0, sa_mask=[], sa_flags=SA_RESTORER, sa_restorer=0x7f305625a510}, {sa_handler=SIG_IGN, sa_mask=[], sa_flags=0}, 8) = 0
rt_sigaction(SIGQUIT, {sa_handler=0x55993f0238b0, sa_mask=[], sa_flags=SA_RESTORER, sa_restorer=0x7f305625a510}, {sa_handler=SIG_DFL, sa_mask=[], sa_flags=0}, 8) = 0
rt_sigaction(SIGTERM, {sa_handler=0x55993f0238b0, sa_mask=[], sa_flags=SA_RESTORER, sa_restorer=0x7f305625a510}, {sa_handler=SIG_DFL, sa_mask=[], sa_flags=0}, 8) = 0
rt_sigaction(SIGTSTP, {sa_handler=0x55993f0238b0, sa_mask=[], sa_flags=SA_RESTORER, sa_restorer=0x7f305625a510}, {sa_handler=SIG_DFL, sa_mask=[], sa_flags=0}, 8) = 0
rt_sigaction(SIGTTIN, {sa_handler=0x55993f0238b0, sa_mask=[], sa_flags=SA_RESTORER, sa_restorer=0x7f305625a510}, {sa_handler=SIG_DFL, sa_mask=[], sa_flags=0}, 8) = 0
rt_sigaction(SIGTTOU, {sa_handler=0x55993f0238b0, sa_mask=[], sa_flags=SA_RESTORER, sa_restorer=0x7f305625a510}, {sa_handler=SIG_DFL, sa_mask=[], sa_flags=0}, 8) = 0
write(4, "Enter passphrase for /home/vlefe"..., 49) = 49
read(4, 0x7ffd198c78cf, 1)              = ? ERESTARTSYS (To be restarted if SA_RESTART is set)
--- SIGINT {si_signo=SIGINT, si_code=SI_KERNEL} ---
rt_sigreturn({mask=[]})                 = -1 EINTR (Interrupted system call)
write(4, "\n", 1)                       = 1
[...]

In the ssh-add strace output when using unison:

[...]
openat(AT_FDCWD, "/dev/tty", O_RDWR)    = 4
ioctl(4, TCGETS, {c_iflag=ICRNL|IUTF8, c_oflag=NL0|CR0|TAB0|BS0|VT0|FF0|OPOST|ONLCR, c_cflag=B38400|CS8|CREAD, c_lflag=ISIG|ICANON|ECHO|ECHOE|ECHOK|IEXTEN|ECHOCTL|ECHOKE, ...}) = 0
ioctl(4, TCGETS, {c_iflag=ICRNL|IUTF8, c_oflag=NL0|CR0|TAB0|BS0|VT0|FF0|OPOST|ONLCR, c_cflag=B38400|CS8|CREAD, c_lflag=ISIG|ICANON|ECHO|ECHOE|ECHOK|IEXTEN|ECHOCTL|ECHOKE, ...}) = 0
ioctl(4, TCSETSF, {c_iflag=ICRNL|IUTF8, c_oflag=NL0|CR0|TAB0|BS0|VT0|FF0|OPOST|ONLCR, c_cflag=B38400|CS8|CREAD, c_lflag=ISIG|ICANON|ECHOE|ECHOK|IEXTEN|ECHOCTL|ECHOKE, ...}) = 0
ioctl(4, TCGETS, {c_iflag=ICRNL|IUTF8, c_oflag=NL0|CR0|TAB0|BS0|VT0|FF0|OPOST|ONLCR, c_cflag=B38400|CS8|CREAD, c_lflag=ISIG|ICANON|ECHOE|ECHOK|IEXTEN|ECHOCTL|ECHOKE, ...}) = 0
rt_sigaction(SIGALRM, {sa_handler=0x55e65c2078b0, sa_mask=[], sa_flags=SA_RESTORER, sa_restorer=0x7f77bb25a510}, {sa_handler=SIG_DFL, sa_mask=[], sa_flags=0}, 8) = 0
rt_sigaction(SIGHUP, {sa_handler=0x55e65c2078b0, sa_mask=[], sa_flags=SA_RESTORER, sa_restorer=0x7f77bb25a510}, {sa_handler=SIG_DFL, sa_mask=[], sa_flags=0}, 8) = 0
rt_sigaction(SIGINT, {sa_handler=0x55e65c2078b0, sa_mask=[], sa_flags=SA_RESTORER, sa_restorer=0x7f77bb25a510}, {sa_handler=SIG_DFL, sa_mask=[], sa_flags=0}, 8) = 0
rt_sigaction(SIGPIPE, {sa_handler=0x55e65c2078b0, sa_mask=[], sa_flags=SA_RESTORER, sa_restorer=0x7f77bb25a510}, {sa_handler=SIG_IGN, sa_mask=[], sa_flags=0}, 8) = 0
rt_sigaction(SIGQUIT, {sa_handler=0x55e65c2078b0, sa_mask=[], sa_flags=SA_RESTORER, sa_restorer=0x7f77bb25a510}, {sa_handler=SIG_DFL, sa_mask=[], sa_flags=0}, 8) = 0
rt_sigaction(SIGTERM, {sa_handler=0x55e65c2078b0, sa_mask=[], sa_flags=SA_RESTORER, sa_restorer=0x7f77bb25a510}, {sa_handler=SIG_DFL, sa_mask=[], sa_flags=0}, 8) = 0
rt_sigaction(SIGTSTP, {sa_handler=0x55e65c2078b0, sa_mask=[], sa_flags=SA_RESTORER, sa_restorer=0x7f77bb25a510}, {sa_handler=SIG_DFL, sa_mask=[], sa_flags=0}, 8) = 0
rt_sigaction(SIGTTIN, {sa_handler=0x55e65c2078b0, sa_mask=[], sa_flags=SA_RESTORER, sa_restorer=0x7f77bb25a510}, {sa_handler=SIG_DFL, sa_mask=[], sa_flags=0}, 8) = 0
rt_sigaction(SIGTTOU, {sa_handler=0x55e65c2078b0, sa_mask=[], sa_flags=SA_RESTORER, sa_restorer=0x7f77bb25a510}, {sa_handler=SIG_DFL, sa_mask=[], sa_flags=0}, 8) = 0
write(4, "Enter passphrase for /home/vlefe"..., 49) = 49
read(4, 

and Ctrl-C does nothing, I suppose because SIGINT is ignored here.

In the unison-2.53-2.53.3 src/remote.ml file:

        (* Signals generated by the terminal from user input are sent to all
           processes in the foreground process group. This means that the ssh
           child process will receive SIGINT at the same time as Unison and
           close the connection before Unison has the chance to do cleanup with
           the remote end. To make matters more complicated, the ssh process
           must be in the foreground process group because interaction with the
           user is done via the terminal (not via stdin, stdout) and background
           processes can't read from the terminal (unless we'd set up a pty
           like is done for the GUI).

           Don't let these signals reach ssh by blocking them.

           The signals could be ignored instead of being blocked because ssh
           does not set handlers for SIGINT and SIGQUIT if they've been ignored
           at startup. But this triggers an error in ssh. The interactive
           passphrase reading function captures these signals for the purpose
           of restoring terminal settings (echo). When receiving a signal, and
           after restoring previous signal handlers, it resends the signal to
           itself. But now the signal is ignored and instead of terminating,
           the process will continue running as if passphrase reading function
           had returned with an empty result.

           Since the ssh process no longer receives the signals generated by
           user input we have to make sure that it terminates when Unison does.
           This usually happens due to its stdin and stdout being closed,
           except for when it is interacting with the user via terminal. To get
           around that, an [at_exit] handler is registered to send a SIGTERM
           and SIGKILL to the ssh process.  (Note, for [at_exit] handlers to
           run, unison process must terminate normally, not be killed. For
           SIGINT, this means that [Sys.catch_break true] (or an alternative
           SIGINT handler) must be set before creating the ssh process.) *)

So, in my case, unison sends SIGINT only to my ssh wrapper. It should
send the signal to the process group in order to mimic what normally
happens with a Ctrl-C.

Then, if I type a character, e.g. "z", ssh-add gets an I/O error, but
it reopens /dev/tty for the next passphrase instead of exiting. I'm
not sure whether this is correct, but via Mutt, the terminal was still
working for ssh-add, so that fixing the issue in unison would be the
only good solution.

write(4, "Enter passphrase for /home/vlefe"..., 49) = 49
read(4, "z", 1)                         = 1
read(4, 0x7ffc8bf3e17f, 1)              = -1 EIO (Input/output error)
write(4, "\n", 1)                       = 1
ioctl(4, TCGETS, {c_iflag=INLCR|ICRNL|IUTF8, c_oflag=NL0|CR0|TAB0|BS0|VT0|FF0|OPOST|ONLCR, c_cflag=B38400|CS8|CREAD, c_lflag=ISIG|ECHOE|ECHOK|IEXTEN|ECHOCTL|ECHOKE, ...}) = 0
ioctl(4, TCSETSF, {c_iflag=ICRNL|IUTF8, c_oflag=NL0|CR0|TAB0|BS0|VT0|FF0|OPOST|ONLCR, c_cflag=B38400|CS8|CREAD, c_lflag=ISIG|ICANON|ECHO|ECHOE|ECHOK|IEXTEN|ECHOCTL|ECHOKE, ...}) = -1 EIO (Input/output error)
rt_sigaction(SIGALRM, {sa_handler=SIG_DFL, sa_mask=[], sa_flags=SA_RESTORER, sa_restorer=0x7f77bb25a510}, NULL, 8) = 0
rt_sigaction(SIGHUP, {sa_handler=SIG_DFL, sa_mask=[], sa_flags=SA_RESTORER, sa_restorer=0x7f77bb25a510}, NULL, 8) = 0
rt_sigaction(SIGINT, {sa_handler=SIG_DFL, sa_mask=[], sa_flags=SA_RESTORER, sa_restorer=0x7f77bb25a510}, NULL, 8) = 0
rt_sigaction(SIGQUIT, {sa_handler=SIG_DFL, sa_mask=[], sa_flags=SA_RESTORER, sa_restorer=0x7f77bb25a510}, NULL, 8) = 0
rt_sigaction(SIGPIPE, {sa_handler=SIG_IGN, sa_mask=[], sa_flags=SA_RESTORER, sa_restorer=0x7f77bb25a510}, NULL, 8) = 0
rt_sigaction(SIGTERM, {sa_handler=SIG_DFL, sa_mask=[], sa_flags=SA_RESTORER, sa_restorer=0x7f77bb25a510}, NULL, 8) = 0
rt_sigaction(SIGTSTP, {sa_handler=SIG_DFL, sa_mask=[], sa_flags=SA_RESTORER, sa_restorer=0x7f77bb25a510}, NULL, 8) = 0
rt_sigaction(SIGTTIN, {sa_handler=SIG_DFL, sa_mask=[], sa_flags=SA_RESTORER, sa_restorer=0x7f77bb25a510}, NULL, 8) = 0
rt_sigaction(SIGTTOU, {sa_handler=SIG_DFL, sa_mask=[], sa_flags=SA_RESTORER, sa_restorer=0x7f77bb25a510}, NULL, 8) = 0
close(4)                                = 0
openat(AT_FDCWD, "/home/vlefevre/.ssh/id_rsa-android", O_RDONLY) = 4
newfstatat(4, "", {st_mode=S_IFREG|0600, st_size=1766, ...}, AT_EMPTY_PATH) = 0
getuid()                                = 1000
newfstatat(4, "", {st_mode=S_IFREG|0600, st_size=1766, ...}, AT_EMPTY_PATH) = 0
read(4, "-----BEGIN RSA PRIVATE KEY-----\n"..., 4096) = 1766
read(4, "", 2330)                       = 0
read(4, "", 4096)                       = 0
close(4)                                = 0
ioctl(0, TCGETS, 0x7ffc8bf3e7e0)        = -1 ENOTTY (Inappropriate ioctl for device)
getpid()                                = 61437
openat(AT_FDCWD, "/dev/tty", O_RDWR)    = 4
[...]

-- 
Vincent Lefèvre <vincent@vinc17.net> - Web: <https://www.vinc17.net/>
100% accessible validated (X)HTML - Blog: <https://www.vinc17.net/blog/>
Work: CR INRIA - computer arithmetic / AriC project (LIP, ENS-Lyon)


Reply to: