I've this problem with my server/client on C. If I close the server socket after a SIGINT, and then I try to write on this closed connection from the client, I've to do write two times before than client generates SIGPIPE. Shouldn't it generate it immediately? Is this a normal behaviour or something I need to fix? This is my code. I'm testing things on ubuntu, same PC, connecting via 127.0.0.1.
server.c
sigset_t set;
struct sigaction sign;
int sock_acc;
int sock;
void closeSig(){
close(sock_acc);
close(sock);
exit(1);
}
int main(){
sigemptyset(&set);
sigaddset(&set, SIGINT);
sig.sa_sigaction = &closeSig;
sig.sa_flags = SA_SIGINFO;
sig.sa_mask = set;
sigaction(SIGINT, &sig, NULL);
//other code to accept the connection from the client
sigprocmask(SIG_UNBLOCK, &set, NULL);
//write/read calls
}
client.c
void closeSigPipe(){
close(ds_sock);
printf("Stop...");
exit(1);
}
int main(){
sigpipe.sa_sigaction = &closeSigPipe;
sigpipe.sa_flags = SA_SIGINFO;
sigaction(SIGPIPE, &sigpipe, NULL);
//other code to connect the server, and write/read calls
}
The problem is that when I close the server terminal with CTRL+C, the first write to the connection from the client works without any problem... perror("Error:"); prints "success"...
The TCP protocol doesn't provide a way for the receiver to tell the sender that it's closing the connection. When it closes the connection, it sends a
FIN
segment, but this just means that it's done sending, not that it can no longer receive.The way the sender detects that the connection has been closed is that it tries to send data, and the receiver sends back a
RST
segment in response. But writing to a socket doesn't wait for the response, it just queues the data and returns immediately. The signal occurs when theRST
is received, which will be a short time later.The reason you have to do two writes may be because of Nagle's Algorithm. To avoid excessive network overhead, TCP tries to combine short messages into a single segment. The Wikipedia page includes some workarounds for this.