Reputation: 1253
I'm trying to force TCP reset on a connection. The suggested way is to set SO_LINGER to 0 and the call close().
I'm doing exactly that, but the connection remains in ESTABLISHED state. The socket is operating in non blocking mode. The operating system is Raspbian.
The code:
struct linger l;
l.l_onoff = 1;
l.l_linger = 0;
if (setsockopt(server->connection_socket, SOL_SOCKET, SO_LINGER, &l, sizeof(l)) != 0) {
LOG_E(tcp, "setting SO_LINGER failed");
}
if (close(server->connection_socket) != 0) {
LOG_E(tcp, "closing socket failed");
}
server->connection_socket = 0;
LOG_I(tcp, "current TCP connection was closed");
Wireshark trace shows no RST as well.
No other threads of the application are performing any operation on that socket.
I can't figure out what is wrong, any suggestion would be much appreciated.
SOLVED
The issue was with file descriptors leaking to children created through system()
call.
In fact when I listed all TCP socket descriptors with lsof -i tcp
, I found out that child processes had opened file descriptor from parent process (even though parent already did not).
The solution was requesting file descriptor to be closed in forked process (right after accept()
).
fcntl(server->connection_socket, F_SETFD, FD_CLOEXEC)
Upvotes: 4
Views: 1662
Reputation: 5055
In your case you can no longer send and receive data after calling close
. Also, after close
call the RST will be sent only if the reference counter of socket descriptor becomes 0. Then the connection goes into CLOSED
state and data in the receive and the send buffers are discarded.
Probably the answer lies in how you forked a process (as mentioned by EJP in comment). It seems that you didn't close the accepted socket in parent process after calling fork
. So the socket reference counter is nonzero and there is no RST immediately after your close
.
Such situations are well described by Stevens in UNIX Network Programming.
Upvotes: 2