Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

write(socket, buff, length) makes crash

Tags:

c

sockets

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

like image 683
McD0n3ld Avatar asked Dec 07 '22 08:12

McD0n3ld


2 Answers

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().

like image 156
user4815162342 Avatar answered Dec 08 '22 21:12

user4815162342


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);
like image 32
Valeri Atamaniouk Avatar answered Dec 08 '22 20:12

Valeri Atamaniouk