3

I'm working on an app which connects to a server via TCP.

If the socket for whatever reason is closed, I end up in the SIGPIPE handler.

What do I do so that recv and send just returns an error on a disconnected/closed socket?

Thanks

user1884325
  • 2,530
  • 1
  • 30
  • 49
  • possible duplicate of [How to prevent SIGPIPEs (or handle them properly)](http://stackoverflow.com/questions/108183/how-to-prevent-sigpipes-or-handle-them-properly) – Martin R Oct 22 '13 at 05:17
  • I read this post, but nothing in that post seems to fix the issue I'm having. I'm probably doing something wrong. – user1884325 Oct 22 '13 at 06:21

6 Answers6

3

I've found ignoring SIGPIPE ineffective on OS X. Use SO_NOSIGPIPE instead. Note this is set on the socket once, as opposed to MSG_NOSIGNAL which is requested in each call to send().

int socket = accept (...); /* (or however you're getting the socket) */
int option_value = 1; /* Set NOSIGPIPE to ON */
if (setsockopt (socket, SOL_SOCKET, SO_NOSIGPIPE, &option_value, sizeof (option_value)) < 0) {
    perror ("setsockopt(,,SO_NOSIGPIPE)");
}
Perette
  • 821
  • 8
  • 17
2

SIG_IGN the signal rather than handling it. send will return -1 and errno will be set to EPIPE.

Duck
  • 26,924
  • 5
  • 64
  • 92
  • What about recv? This --> signal(SIGPIPE, SIG_IGN) doesn't seem to help. I still get a SIGPIPE. I guess recv just blocks until the socket is closed? If the connection is dropped for whatever reason, what will recv return? Just 0? – user1884325 Oct 22 '13 at 06:19
  • 1
    `read()` and `recv()` return `0` if the peer closed or shut down the connection. See `man read` or `man recv` for details. If still unclear pose another question on this differnt topic. – alk Oct 22 '13 at 06:45
  • As alk said you don't have to worry about sigpipe with recv. If the socket peer closed you will get the normal shutdown notification of a zero read. The `signal` system call semantics are non-standard across platforms. On linux you can coax it to behave the way you want through feature test macros but I don't know what OSX defaults to. Better to use `sigaction` and I see that alk has left an answer describing how to do that. – Duck Oct 22 '13 at 13:50
2

To ignore a signal set the signal handler to SIG_IGN doing so:

struct sigaction sa;
memset(&sa, 0, sizeof(sa));

sa.sa_handler = SIG_IGN;

if (-1 == sigaction(SIGPIPE, &sa, NULL))
{
  perror("sigaction() failed");
}
alk
  • 69,737
  • 10
  • 105
  • 255
2

Ignoring SIGPIPE as described in other answers (ie. signal(SIGPIPE, SIG_IGN);) worked for me on OS X. Also be sure to test outside a debugger as it says in this comment. I was debugging with lldb and its signal handling was terminating my program with SIGPIPE even though I'd ignored that signal. Testing outside of lldb worked fine.

Community
  • 1
  • 1
user2683747
  • 151
  • 1
  • 9
0

use signal handler or ignore it

#include <signal.h>
signal(SIGPIPE, SIG_IGN);

while writing to a socket first check if socket fd is positive or not in program. Externally you should check that you are sending pointer of a valid socket

Gaurav
  • 2,003
  • 1
  • 25
  • 50
  • did you use #include ?? – Gaurav Oct 22 '13 at 06:21
  • @user1884325: If using `signal()` you most probably need to reapply the handler after having been used once. Do not use `signal` use sigaction()`. – alk Oct 22 '13 at 06:47
  • yes sigaction is more descriptive and more useful but POSIX.1 and signal is basic but it is a feature of ISO C – Gaurav Oct 22 '13 at 06:51
0

You can ignore SIGPIPE

 #include <signal.h>

signal(SIGPIPE, SIG_IGN);

Or you can use signal handler.

signal(SIGPIPE, handler);
void handler(int signal)
{   
    //("Signal caught");

}
Parag Bafna
  • 22,812
  • 8
  • 71
  • 144
  • Do not `printf()` from signl handlers, as `printf()` is not guaranteed to be signal safe. – alk Oct 22 '13 at 06:49