user1256821
user1256821

Reputation: 1178

write() returns correct number of bytes despite terminating the client

I have a multihreaded client-server application. The first thread is a "listener" which adds client to a array of a file descriptors:

while (1) {
    if ((connfd = accept(listenfd_service, (struct sockaddr *) &cliaddr, &clilen)) > 0) {
        printf("service connected...\n");
        int i;
        for (i = 0; i < MAX_SERVICES; i++) {
            if (service_sockets[i] == -1) {
                service_sockets[i] = connfd;
                break;
            }
        }
    }
}

The problem is that when I terminate the client with Ctrl+C and run the following lines

for (j = 0; j < MAX_SERVICES; j++) {
    if (service_sockets[j] != -1) {
        int test = write(service_sockets[j], c, 72);
        if (test == -1) {
            service_sockets[j] = -1;
        }
    }
}

I get a 72 in a 'test' variable. If I try to run these lines second time, I get a SIGPIPE signal.

Upvotes: 4

Views: 94

Answers (1)

Chris Dodd
Chris Dodd

Reputation: 126203

That's normal and expected behavior. The server won't find out immediately when the client exits, as normally when there's no data going over a network connection, there's no data being transmitted. Instead, the next time the server sends data it will send off a packet (that's your successful write of 72 bytes), and the client machine (if the OS is still running) will respond with a "Connection Reset" message. This will cause the server OS to close its end of the connection, causing a SIGPIPE/EPIPE when the server next writes to the socket.

The normal way of dealing with this is to ignore SIGPIPE signals, and handle the write returning an EPIPE error. Pretty much any process which deals with multiple connections and may have one go away while others are still useful needs to ignore SIGPIPEs.

Upvotes: 4

Related Questions