4

I have a multithreaded SSL server written in C, whose behavior is as follows:

  • Main thread waits for client requests (epoll), accepts them and spawns a detached thread for each client socket
  • Each thread does SSL_accept separately. After successful SSL handshake, the thread receives messages from the client and responds back with a message for each SSL_read.
  • Client threads exit when clients close socket or any error occurs.

I tried simulating concurrent client connections to test the server.

During one such simulation, my server exited with SIGPIPE signal.

Is there a way to catch and handle SIGPIPE at thread level? I want the respective thread to handle the signal instead of the entire process exiting.

Initially I tried signal(SIGPIPE,SIG_IGN), but signal(2) man says:

The effects of signal() in a multithreaded process are unspecified.

Can signalfd be used to handle such SIGPIPEs? Or are there other solutions?

Note:Server runs on Ubuntu 12.04 and I can't use MSG_NOSIGNAL on send since I am using the OpenSSL as library directly (no source code)

Thanks in advance.

Nataraj
  • 379
  • 7
  • 18
  • 1
    possible duplicate of [How to prevent SIGPIPEs (or handle them properly)](http://stackoverflow.com/questions/108183/how-to-prevent-sigpipes-or-handle-them-properly) – Zan Lynx May 27 '14 at 12:11
  • No. That post doesn't speak about multi threaded environment. I have already tried the options mentioned in that post. – Nataraj May 27 '14 at 12:12
  • It may be unspecified but you won't have problems if you do it before creating threads. Ignoring signaals is easy. – Zan Lynx May 27 '14 at 12:13
  • So? It is still the right answer. – Zan Lynx May 27 '14 at 12:13
  • I tried SIG_IGN on SIGPIPE for each new thread. It did not help me. Does doing signal(SIGPIPE,SIG_IGN) before creating any thread help? – Nataraj May 27 '14 at 12:16
  • Is there really no way to do the actual send()s yourself with OpenSSL? It seems like there would be, in which case you can easily pass MSG_NOSIGNAL. – John Zwinck May 27 '14 at 12:17
  • If you get SIGPIPE after ignoring it sounds like the program is resetting the handler somewhere else. – Zan Lynx May 27 '14 at 12:21
  • @Johg Swinck . Sadly,I don't have the source code of OpenSSL library. Installed it using `apt-get`. – Nataraj May 27 '14 at 12:23
  • @ZanLynx Maybe I am doing it wrong? I am doing it for each new thread. – Nataraj May 27 '14 at 12:32

1 Answers1

6

Is there a way to catch and handle SIGPIPE at thread level? I want the respective thread to handle the signal instead of the entire process exiting.

Yes, there is. You need to block the signal in all threads except one (it would be best to do this before creating any thread). If you are using pthreads, you can use pthread_sigmask as this will guarantee, that after calling it every created thread will inherit signal mask. Then in one specific thread you need to register a handler (don't use signal, it's obsolete) with sigaction.

When signal reaches your process it will be blocked until this one thread will continue it's work on process (only then the signal is received by process, that's why it's unspecified behavior - it depends on which thread is running, but by blocking signal on all other threads you specify which one can react to it).

Other way around:

If you want to not receive this signal ever ever and be aware of which socket was broken with it, you can only use pthread_sigmask and ignore this signal for all threads. Then function, which broke because of SIGPIPE should return -1 (I'm not familiar with openssl, but when it comes to sockets, it's write way of saying, the socket was closed on the other side).

zoska
  • 1,684
  • 11
  • 23
  • Thanks. If my interpretation is correct, you are suggesting me to have a dedicated thread to handle signal and block signals on all other threads? But how do I find for which thread SIGPIPE got raised? I need to close the client socket (which caused SIGPIPE) properly and exit that particular thread. – Nataraj May 27 '14 at 12:29
  • I used `pthread_sigmask` and ignored `SIGPIPE` for all threads. I have not seen any abnormal exit so far. Ran a few tests. Thanks. – Nataraj Jun 05 '14 at 10:01