1
votes

Is there is a way for a process to detect which side of a TCP connection triggered the first FIN? My Process or Network entity that my process communicates with.

Let's say I have a multithreaded process on Linux that one of its sockets handles an established TCP socket with other network entity.

Theoretically, one thread in my process can close the socket that is handled (select/read/send) by a second thread.

Is there are way to detect which side of the connection triggered first the disconnection?

3
The side that first receives an EOS is the side that didn't trigger the disconnection. Surely you know whether you've done a close, or whether or not you've received an EOS?user207421
Surely I can program it to know, but I wanted to know if I can relay on the socket API. the problem is that other thread in my program can trigger the close/shutdown, so getting EOS in the thread that handles the socket doesn't assure whether it was triggered internally (by this program) or from the peer entityYanivN
Getting EOS means the peer has closed the connection. That can only happen if the connection is still open at your end. Ergo you haven't closed it. You could have shut it down for output, which would cause EOS at the peer, which should cause him to close, and there are ways to detect whether you did shut it down for output, starting with a simple per-socket boolean, but unless you're doing that I really don't see the problem.user207421

3 Answers

0
votes

If you are using select() or something like it (poll(), epoll(), kqueue(), etc.), then the socket should always be monitored for read readiness. When a recv()(or read()) on a socket returns 0, it means the other end has issued a shutdown on the socket (either with a call to shutdown() or close()).

If you want an API to detect whether or not you have already issued a half close with shutdown(), a send() (or write()) on the socket will trigger SIGPIPE. If SIGPIPE is ignored, or if send() is passed the MSG_NOSIGNAL flag, then an EPIPE error will be the result instead.

If a thread has already called close() on a socket, it would be an error for that thread to attempt any I/O on the socket. The result can be non-deterministic since the socket file descriptor may get reused by the process for some other purpose. This kind of error is similar to having a stale pointer to freed memory that has been allocated by some other thread.

0
votes

Just associate some kind of application-level structure with the socket. Have a rule that if a thread wishes to shutdown or terminate the connection, it must so indicate in the application-level structure.

All of the threads in a process are supposed to be cooperating. You shouldn't need to "reach into" a thread to find out what it did or make it do the right thing. It should be coded to inform other threads of what they need to know.

0
votes

Is there is a way for a process to detect which side of a TCP connection triggered the first FIN?

tcpdump can show you it. This is an example. A server application listens on 7752 port. A client first established a connection and then the client closes the connection. So this is the output:

# tcpdump -i lo 'tcp[13] & 1 != 0'
11:12:28.613424 IP localhost.50631 > localhost.7752: Flags [F.], seq 12878459, ack 4245407789, win 276, options [nop,nop,TS val 3690514841 ecr 3690513840], length 0
11:12:28.613720 IP localhost.7752 > localhost.50631: Flags [F.], seq 1, ack 1, win 256, options [nop,nop,TS val 3690514841 ecr 3690514841], length 0