If I run

strace -e trace=ioctl -v ssh some_remote_host

I see a line like this:

ioctl(0, SNDCTL_TMR_STOP or TCSETSW, {c_iflags=0x6006, c_oflags=0x4, c_cflags=0x
4bf, c_lflags=0xa00, c_line=0, c_cc[VMIN]=1, c_cc[VTIME]=0, c_cc="\x03\x1c\x7f\x
15\x04\x00\x01\xff\x11\x13\x1a\xff\x12\x0f\x17\x16\xff\x00\x00"}) = 0

Which makes sense: ssh has to change a lot of terminal settings, for example:

  • it turns off ISIG because ^C and ^Z should interrupt and suspend the process on the remote host, not the ssh process running locally;
  • it turns off ICANON because it wants to receive keyboard input unbuffered rather than line buffered;
  • it turns off ECHO because whether echoing occurs should depend on the attributes set on the remote host's pseudo-terminal, instead of occurring automatically on the local terminal

If you now exit the ssh session, the original terminal attributes are restored by a second ioctl call:

ioctl(0, SNDCTL_TMR_STOP or TCSETSW, {c_iflags=0x6d02, c_oflags=0x5, c_cflags=0x
4bf, c_lflags=0x8a3b, c_line=0, c_cc="\x03\x1c\x7f\x15\x04\x00\x01\xff\x11\x13\x
1a\xff\x12\x0f\x17\x16\xff\x00\x00"}) = 0

But what I find strange is that even if ssh is killed with SIGKILL before it has the chance to make the second ioctl call, you get the original terminal attributes back. Otherwise you would notice that something is very wrong (for example commands typed into the shell would not be echoed). How does ssh manage to ensure that the original terminal attributes are restored even if it's not around to call ioctl again?


1 Answer 1


The shell knows that ssh died and can reset the terminal.

Tracing a bash shell while I kill a child ssh shows that it makes several ioctl() calls.

--- SIGCHLD (Child exited) @ 0 (0) ---
ioctl(255, TIOCSPGRP, [52631])          = 0
ioctl(0, TIOCGWINSZ, {ws_row=25, ws_col=147, ws_xpixel=902, ws_ypixel=329}) = 0
ioctl(0, TIOCSWINSZ, {ws_row=25, ws_col=147, ws_xpixel=902, ws_ypixel=329}) = 0
ioctl(0, SNDCTL_TMR_TIMEBASE or TCGETS, {c_iflags=0x500, c_oflags=0x5, c_cflags=0xbf, c_lflags=0x8a3b, c_line=0, c_cc="\x03\x1c\x7f\x15\x04\x00\x01\x00\x11\x13\x1a\x00\x12\x0f\x17\x16\x00\x00\x00"}) = 0
ioctl(0, SNDCTL_TMR_STOP or TCSETSW, {c_iflags=0x400, c_oflags=0x5, c_cflags=0xbf, c_lflags=0x8a31, c_line=0, c_cc[VMIN]=1, c_cc[VTIME]=0, c_cc="\x03\x1c\x7f\x15\x04\x00\x01\x00\x11\x13\x1a\x00\x12\x0f\x17\x00\x00\x00\x00"}) = 0

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .