0

In C with this code, I am getting a SIGPIPE with send:

        if ( ( nWrite = send( d->descriptor, txt + iStart, nBlock, 0 ) ) < 0 )

The full backtrace:

Program received signal SIGPIPE, Broken pipe.
0xb7fe37f2 in _dl_sysinfo_int80 () from /lib/ld-linux.so.2
#0  0xb7fe37f2 in _dl_sysinfo_int80 () from /lib/ld-linux.so.2
#1  0xb7d654a1 in send () from /lib/libc.so.6
#2  0x08085646 in write_to_descriptor (d=0x97a6028, txt=0x8316b28 "Idle timeout... disconnecting.\n\r", length=32) at comm.c:1750
#3  0x080828a8 in game_loop () at comm.c:823
#4  0x08081b49 in main (argc=2, argv=0xbffffb54) at comm.c:425
(gdb) f 2
#2  0x08085646 in write_to_descriptor (d=0x97a6028, txt=0x8316b28 "Idle timeout... disconnecting.\n\r", length=32) at comm.c:1750
1750            if ( ( nWrite = send( d->descriptor, txt + iStart, nBlock, 0 ) ) < 0 )

Variable info:

(gdb) p nWrite
$4 = 0

(gdb) p d->descriptor
$5 = 14

(gdb) p txt
$6 = 0x8316b28 "Idle timeout... disconnecting.\n\r"

(gdb) p iStart
$7 = 0

(gdb) p nBlock
$8 = 32

Is there a specific ifcheck I should be doing to account for a closed socket here?

I have this already in the game loop:

signal( SIGPIPE, SIG_IGN );
signal( SIGALRM, caught_alarm );
Zeno
  • 1,769
  • 7
  • 33
  • 61
  • 1
    You can send with `MSG_NOSIGNAL` flag so you don't get a `SIGPIPE` when the other end closes. – alvits Feb 10 '17 at 01:24
  • Or you could catch the `SIGPIPE` and handle it with your custom signal handler. – alvits Feb 10 '17 at 01:26
  • You can start with: [`signal(SIGPIPE, SIG_IGN)`](http://stackoverflow.com/questions/108183/how-to-prevent-sigpipes-or-handle-them-properly), and then consider more sophisticated signal handling. A signal handler is quite limited in what it can do *safely*. – Brett Hale Feb 10 '17 at 01:31
  • @BrettHale Oh weird, I have this already in the game loop: `signal( SIGPIPE, SIG_IGN );` – Zeno Feb 10 '17 at 01:38
  • `signal()` is not meant for multi-threaded. If your code is multi-threaded, you need to use `pthread_sigmask()`. – alvits Feb 10 '17 at 01:46
  • @alvits - if he calls `signal()` early enough before spawning child threads, don't the child threads inherit the signal mask? (Otherwise, I might have a bug in *my code*) – selbie Feb 10 '17 at 01:50
  • @selbie - No. `pthread_sigmask()` is what each threads inherit. `signal()` is not for multithreaded apps. Even when called at the beginning of the code. – alvits Feb 10 '17 at 01:51
  • In here http://man7.org/linux/man-pages/man2/signal.2.html the note clearly states _The effects of signal() in a multithreaded process are unspecified_. – alvits Feb 10 '17 at 01:52
  • Could you post a sample code of how to disable SIGPIPE on a *per-thread* basis? I was always confused between whether the SIG_BLOCK flag means "ignore" vs "can throw". – selbie Feb 10 '17 at 01:58
  • @selbie - using the OP's code, it would be `send( d->descriptor, txt + iStart, nBlock, MSG_NOSIGNAL)` – alvits Feb 10 '17 at 01:59
  • @selbie - for everything else using `pthread_sigmask` the following code is how it is done. `sigemptyset(&signals2block); sigaddset(&signals2block, SIGPIPE);pthread_sigmask(SIG_BLOCK, &signals2block, NULL);`. From here on, new threads will inherit this mask. – alvits Feb 10 '17 at 02:01
  • Using `sigaction()` instead of `signal()` is also valid. – Jonathan Leffler Feb 10 '17 at 03:19
  • @alvits The code (a MUD) is single – Zeno Feb 10 '17 at 03:46
  • Since it is a multiplayer game, how do you handle each user? Multi-process? Or just single process with multiplexed file descriptors using `select()`? Just go with `send( d->descriptor, txt + iStart, nBlock, MSG_NOSIGNAL)`. It will make your life easier. – alvits Feb 10 '17 at 03:49
  • @alvits - Thanks. I will apply that solution after I re-read up on it. IIRC, `MSG_NOSIGNAL` is not portable (e.g. doesn't exist on Mac). Could you let me know what you think of the accepted answer for [this question](http://stackoverflow.com/questions/108183/how-to-prevent-sigpipes-or-handle-them-properly) which is in contrast to what you are suggesting. I'm thinking about code I wrote 4 or 5 years ago using `signal(SIGPIPE, SIG_IGN)`, and felt that I had sufficiently researched that it was safe to block SIGPIPE that way. – selbie Feb 10 '17 at 03:59
  • @alvits I know it's not multi-process, and it's not multithreaded either. It must be multiplexed. I'll try NOSIGNAL, thanks! – Zeno Feb 10 '17 at 04:25

0 Answers0