3

I have a loop which keeps writing data to a client through TCP/IP. The connection is opened as follows:

newsockfd = accept(sockfd,
            (struct sockaddr *) &cli_addr,
            &clilen);

The following line is executed continuously in a loop (with sleep of 0.1 sec) in order to write the data to the client:

n = write(newsockfd,data.c_str(),data.length()+1); //+1 to include NULL in null terminated string
if(n>=0)
{
    cout<<"success"<<endl;
}
else
{
    cout<<"Fail"<<endl;
    close(newsockfd);
    newsockfd = -1;
}

I want the server to become reading for receiving a new connections if the connection is broken for any reason. So if writing fails, I get ready again to accept a new connection with the first command.

My problem is the following: the method succeeds for the first time, so if the connection is broken from the client, write() returns a negative number and I know immediately that the connection has a problem, so I close it and expect a new one. The server receives the new connection, but at the next time when using write(), the program crashes immediately.

Why does this happen? Please help, I'm new in TCP/IP stuff.

Please ask for more information if you require it.

Requested from helpers:

Stack trace:

Error: signal 13:

    /mnt/hgfs/Dropbox/common_src/LinuxTCP/Server/ServerLinux-build-desktop-Qt_4_8_1_in_PATH__System__Release/ServerLinux[0x402155]
    /lib/x86_64-linux-gnu/libc.so.6(+0x364a0)[0x7ffc57ac04a0]
    /lib/x86_64-linux-gnu/libpthread.so.0(write+0x10)[0x7ffc5836dcb0]
    /mnt/hgfs/Dropbox/common_src/LinuxTCP/Server/ServerLinux-build-desktop-Qt_4_8_1_in_PATH__System__Release/ServerLinux[0x4023b6]
    /mnt/hgfs/Dropbox/common_src/LinuxTCP/Server/ServerLinux-build-desktop-Qt_4_8_1_in_PATH__System__Release/ServerLinux[0x401b54]
    /lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xed)[0x7ffc57aab76d]
    /mnt/hgfs/Dropbox/common_src/LinuxTCP/Server/ServerLinux-build-desktop-Qt_4_8_1_in_PATH__System__Release/ServerLinux[0x402081]

Variable definitions: it's a class:

Body:

int sockfd, portno, n;
struct sockaddr_in serv_addr;
struct hostent *server;

Constructor starts the stuff:

LinuxTCPServer::LinuxTCPServer(int port, bool nonblocking)
{
if(nonblocking)
    sockfd = socket(AF_INET, SOCK_NONBLOCK | SOCK_STREAM, 0);
else
    sockfd = socket(AF_INET, SOCK_STREAM, 0);

if (sockfd < 0)
   error("ERROR opening socket");
bzero((char *) &serv_addr, sizeof(serv_addr));
portno = port;

serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = INADDR_ANY;
serv_addr.sin_port = htons(portno);

if (bind(sockfd, (struct sockaddr *) &serv_addr,
         sizeof(serv_addr)) < 0)
         error("ERROR on binding");

listen(sockfd,5);
clilen = sizeof(cli_addr);
}
The Quantum Physicist
  • 24,987
  • 19
  • 103
  • 189

2 Answers2

5

Assuming Linux >= 2.2, replace this:

n = write(newsockfd,data.c_str(),data.length()+1);

with this:

n = send(newsockfd, data.c_str(), data.length()+1, MSG_NOSIGNAL);

send(2) will then return -1 with errno set to EPIPE, rather than generating a fatal SIGPIPE. Alternatively, ignore SIGPIPE.

When you receive the SIGPIPE, the connection behind newsockfd has been broken. We don't have enough code to reproduce the problem, client and server, so it's rather moot to say what might actually be wrong. However, converting SIGPIPEs to EPIPEs will at least give your server a chance to handle the broken connection.

pilcrow
  • 56,591
  • 13
  • 94
  • 135
  • Thank you for the answer, I have another question though. Does read() produce the SIGPIPE? and what is the alternative to it? can I just use MSG_NOSIGNAL with it as well? I didn't find that common out there. – The Quantum Physicist Apr 03 '13 at 20:35
  • 1
    @SamerAfach, no. A read(2)/recv(2)/recvfrom(2)/recvmsg(2) will report a broken connection with a -1 return and ECONNRESET. – pilcrow Apr 03 '13 at 21:07
2

Your stack trace indicates that the program is crashing with signal 13, which means you have a broken pipe.

That would indicate that your connection is broken, but you are still trying to write to it. See this thread for why that might causes the broken pipe error: What causes the Broken Pipe Error?

Now, on how to solve the issue, I suspect you're not actually getting a proper connection setup on your 'accept' call. Make sure you check the status of your 'accept' call before calling write.

The problems that are causing your accept call to fail are likely on the other side of the connection I think.

Community
  • 1
  • 1
2to1mux
  • 773
  • 5
  • 7