McD0n3ld
McD0n3ld

Reputation: 199

write(socket, buff, length) makes crash

I have a program that sends data to a mobile phone with android. Let's iamgine

//EDIT

while(enviado < length) {
    printf("SEND\n");
    r = write(con, buff_enviar+enviado, length-enviado);
    printf(" OK\n");
    if (r > 0) enviado += r;
    else if (r == 0) { printf(" * >> Socket cerrado [datos] (%d)\n",r); return r; }
    else if (r == -1) { printf(" * >> Error [datos] (%d)\n",r); return r; }
}

When I'm out of this while, I change buff_enviar values. When I cancel the transmission in my phone, by doing a successful socket.close(), the write makes my program end for no reason. So the output of my program is:

SEND OK SEND OK SEND

I guess it's write fault because it does not printf OK. ERRNO value is 61 (No data available)

I hope someone has encountered this problem before and solved it.

EDIT: Sometimes when I cancel, r = -1 so I can handle the error, but most of the time it just terminates the program. It's like randomly chosen. I'm confused :(

Kind regards, Raúl

Upvotes: 4

Views: 2828

Answers (3)

andrea ciuffoli
andrea ciuffoli

Reputation: 161

Also in my case there was many crash of the program without core dump

signal (SIGPIPE, SIG_IGN);

this line at the begin of the program have solved the problem!

Upvotes: 0

Valeri Atamaniouk
Valeri Atamaniouk

Reputation: 5163

Though the chosen answer was to ignore signal process wide, there are other alternatives:

Using send function with MSG_NOSIGNAL:

send(con, buff_enviar+enviado, length-enviado, MSG_NOSIGNAL);

Disabling SIGPIPE on socket level (not available on all kernels):

int flag = 1;
setsockopt(con, SOL_SOCKET, SO_NOSIGPIPE, &flag, sizeof(flag));

Disabling SIGPIPE for caller thread:

sigset_t set;
sigemptyset (&set);
sigaddset (&set, SIGPIPE);
pthread_sigmask(SIG_BLOCK, &set, NULL);

And, finally, disabling signal process-wide (not recommended for libraries):

signal(SIGPIPE, SIG_IGN);

Upvotes: 7

user4815162342
user4815162342

Reputation: 155126

You are writing to a closed socket, which by default generates a "broken pipe" signal (SIGPIPE). To be able to reliably recover from write(), you need to ignore EPIPE by calling:

signal (SIGPIPE, SIG_IGN);

somewhere in your program, for example in main().

Upvotes: 9

Related Questions