Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

send() crashes my program

Tags:

c++

I'm running a server and a client. i'm testing my program on my computer.

this is the funcion in the server that sends data to the client:

int sendToClient(int fd, string msg) {

    cout << "sending to client " << fd << " " << msg <<endl;
    int len = msg.size()+1;
    cout << "10\n";
    /* send msg size */
    if (send(fd,&len,sizeof(int),0)==-1) {
        cout << "error sendToClient\n";
        return -1;
    }
    cout << "11\n";
    /* send msg */
    int nbytes = send(fd,msg.c_str(),len,0); //CRASHES HERE
    cout << "15\n";
    return nbytes;
}

when the client exits it sends to the server "BYE" and the server is replying it with the above function. I connect the client to the server (its done on one computer, 2 terminals) and when the client exits the server crashes - it never prints the 15. any idea why ? any idea how to test why?

thank you.

EDIT: this is how i close the client:

void closeClient(int notifyServer = 0) {

/** notify server before closing */
if (notifyServer) {
    int len = SERVER_PROTOCOL[bye].size()+1;
    char* buf = new char[len];
    strcpy(buf,SERVER_PROTOCOL[bye].c_str());   //c_str - NEED TO FREE????
    sendToServer(buf,len);
    delete[] buf;
}
close(_sockfd);
}

btw, if i skipp this code, meaning just leave the close(_sockfd) without notifying the server everything is ok - the server doesn't crash.

EDIT 2: this is the end of strace.out:

5211  recv(5, "BYE\0", 4, 0)            = 4
5211  write(1, "received from client 5 \n", 24) = 24
5211  write(1, "command: BYE msg: \n", 19) = 19
5211  write(1, "BYEBYE\n", 7)           = 7
5211  write(1, "response = ALALA!!!\n", 20) = 20
5211  write(1, "sending to client 5 ALALA!!!\n", 29) = 29
5211  write(1, "10\n", 3)               = 3
5211  send(5, "\t\0\0\0", 4, 0)         = 4
5211  write(1, "11\n", 3)               = 3
5211  send(5, "ALALA!!!\0", 9, 0)       = -1 EPIPE (Broken pipe)
5211  --- SIGPIPE (Broken pipe) @ 0 (0) ---
5211  +++ killed by SIGPIPE +++

broken pipe can kill my program?? why not just return -1 by send()??

like image 400
Asher Saban Avatar asked May 28 '11 16:05

Asher Saban


5 Answers

You may want to specify MSG_NOSIGNAL in the flags:

int nbytes = send(fd,msg.c_str(), msg.size(), MSG_NOSIGNAL);
like image 113
etienne Avatar answered Oct 20 '22 20:10

etienne


You're getting SIGPIPE because of a "feature" in Unix that raises SIGPIPE when trying to send on a socket that the remote peer has closed. Since you don't handle the signal, the default signal-handler is called, and it aborts/crashes your program.

To get the behavior your want (i.e. make send() return with an error, instead of raising a signal), add this to your program's startup routine (e.g. top of main()):

#include <signal.h>

int main(int argc, char ** argv)
{
   [...]
   signal(SIGPIPE, SIG_IGN); 
like image 41
Jeremy Friesner Avatar answered Oct 20 '22 19:10

Jeremy Friesner


Probably the clients exits before the server has completed the sending, thus breaking the socket between them. Thus making send to crash.

link

This socket was connected but the connection is now broken. In this case, send generates a SIGPIPE signal first; if that signal is ignored or blocked, or if its handler returns, then send fails with EPIPE.

like image 24
George Kastrinis Avatar answered Oct 20 '22 18:10

George Kastrinis


If the client exits before the second send from the server, and the connection is not disposed of properly, your server keeps hanging and this could provoke the crash.

Just a guess, since we don't know what server and client actually do.

like image 33
sergio Avatar answered Oct 20 '22 19:10

sergio


I find the following line of code strange because you define int len = msg.size()+1;.

int nbytes = send(fd,msg.c_str(),len,0); //CRASHES HERE

What happens if you define int len = msg.size();?

like image 43
Chris Frederick Avatar answered Oct 20 '22 18:10

Chris Frederick