How comes a socat listener knows that the process that connected to it has been KILLed?
4
votes
1
answer
678
views
As far as I understand, once a TCP connection is established, there's no actual flow of data unless one of the two ends actually sends a message, they are both blocked on a call to receive a message. As in, it's not like either end is sending periodic messages to the other one saying "just to let you know, I'm still alive".
If that's the case, then I would expect that if either end of the communication channel was _abruptly_ shut down (e.g.
kill -KILL it
, but also just unplug the power cable of the whole machine), then the other end would not know.
Going to a concrete example, I can establish a connection between two terminals via socat
:
- listen from one terminal and take note of the PID
$ socat -d4 TCP-LISTEN:12345 -
$ # ctrl-z
$ jobs -l
+ 958602 Stopped socat -d4 TCP-LISTEN:12345 -
$ fg
- connect from the other terminal and take note of that PID too
$ socat -d4 TCP-CONNECT:localhost:12345 -
$ # ctrl-z
$ jobs -l
+ 958730 Stopped socat -d4 TCP-CONNECT:localhost:12345 -
$ fg
(Both socat
commands spit out quite a bit of output because of the -d4
debug messages.)
Now, if I open a third terminal end issue
$ kill -KILL 958730
I see Killed
being printed in the _second_ terminal, with no more debug lines from socat
than those that were printed before, but in the _first_ terminal I do see more output:
2025/02/10 18:04:42 socat D select -> (, 0x0, 0x0, 0x0, NULL/0.000000), 1
2025/02/10 18:04:42 socat D read(122, 0x61dbb1b48000, 8192)
2025/02/10 18:04:42 socat D read -> 0
2025/02/10 18:04:42 socat N socket 1 (fd 122) is at EOF
2025/02/10 18:04:42 socat D data loop: sock1->eof=3, sock2->eof=0, closing=1, wasaction=1, total_to={0.1000000}
2025/02/10 18:04:42 socat D select(1, &0x1, &0x0, &0x0, &0.500000)
2025/02/10 18:04:43 socat D select -> (, 0x0, 0x0, 0x0, &0.000000), 0
2025/02/10 18:04:43 socat I poll timed out (no data within 0.500000 seconds)
2025/02/10 18:04:43 socat I shutdown(122, 2)
2025/02/10 18:04:43 socat D shutdown() -> 0
2025/02/10 18:04:43 socat D tcsetattr(0, 0, {00006506,00000005,000000bf,00008a3b, 15,15, 03,1c,7f,15,04,00,01,00,11,13,1a,00,12,0f,17,16,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00})
2025/02/10 18:04:43 socat D tcsetattr() -> 0
2025/02/10 18:04:43 socat D tcsetattr(1, 0, {00006506,00000005,000000bf,00008a3b, 15,15, 03,1c,7f,15,04,00,01,00,11,13,1a,00,12,0f,17,16,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00})
2025/02/10 18:04:43 socat D tcsetattr() -> 0
2025/02/10 18:04:43 socat N exiting with status 0
2025/02/10 18:04:43 socat D exit(0)
2025/02/10 18:04:43 socat D starting xioexit()
2025/02/10 18:04:43 socat D finished xioexit()
But I don't understand, if [SIGKILL
can't be caught/handled in user code because it's handled directly by the kernel](https://stackoverflow.com/a/35570675/5825294) , then 958730
should have no chance of doing anything like sending a message to say "sorry, I'm dying", and therefore 958602
should never know about it.
Where's the flaw in my reasoning?
Asked by Enlico
(2258 rep)
Feb 10, 2025, 06:14 PM
Last activity: Feb 10, 2025, 06:38 PM
Last activity: Feb 10, 2025, 06:38 PM