From 2828422e92afeec5d87f1dc45c57271688aefadd Mon Sep 17 00:00:00 2001 From: Bill Somerville Date: Mon, 22 May 2017 21:51:08 +0100 Subject: [PATCH] Stop rigctld and rotctld crashing when service threads cannot write to clients Although there is no reasonable recovery from SIGPIPE we do not want to terminate the server process, just the client servicing thread. We do this by setting the disposition for SIGPIPE to ignored, this causes an EPIPE to be returned from blocked write() and send() calls that end up trying to send to a broken pipe/socket. --- configure.ac | 2 +- tests/rigctld.c | 32 ++++++++++++++++++++++++++------ tests/rotctld.c | 32 ++++++++++++++++++++++++++------ 3 files changed, 53 insertions(+), 13 deletions(-) diff --git a/configure.ac b/configure.ac index 58aa4472d..8d588dc0f 100644 --- a/configure.ac +++ b/configure.ac @@ -234,7 +234,7 @@ AC_SUBST([NET_LIBS]) dnl Checks for library functions. AC_CHECK_FUNCS([cfmakeraw floor getpagesize getpagesize gettimeofday inet_ntoa \ -ioctl memchr memmove memset pow rint select setitimer setlocale sigaction \ +ioctl memchr memmove memset pow rint select setitimer setlocale sigaction signal \ snprintf socket sqrt strchr strdup strerror strncasecmp strrchr strstr strtol]) AC_FUNC_ALLOCA diff --git a/tests/rigctld.c b/tests/rigctld.c index a593da3a3..2197c1af0 100644 --- a/tests/rigctld.c +++ b/tests/rigctld.c @@ -33,6 +33,7 @@ #include #include #include +#include #include @@ -172,6 +173,12 @@ int main(int argc, char *argv[]) char host[NI_MAXHOST]; char serv[NI_MAXSERV]; +#ifdef HAVE_PTHREAD + pthread_t thread; + pthread_attr_t attr; +#endif + struct handle_data *arg; + while (1) { int c; int option_index = 0; @@ -523,16 +530,29 @@ int main(int argc, char *argv[]) exit(1); } +#ifdef SIGPIPE + /* Ignore SIGPIPE as we will handle it at the write()/send() calls + that will consequently fail with EPIPE. All child threads will + inherit this disposition which is what we want. */ +#if HAVE_SIGACTION + struct sigaction act; + memset (&act, 0, sizeof act); + act.sa_handler = SIG_IGN; + act.sa_flags = SA_RESTART; + if (sigaction (SIGPIPE, &act, NULL)) { + handle_error (RIG_DEBUG_ERR, "sigaction"); + } +#elif HAVE_SIGNAL + if (SIG_ERR == signal (SIGPIPE, SIG_IGN))) + handle_error (RIG_DEBUG_ERR, "signal"); + } +#endif +#endif + /* * main loop accepting connections */ do { -#ifdef HAVE_PTHREAD - pthread_t thread; - pthread_attr_t attr; -#endif - struct handle_data *arg; - arg = malloc(sizeof(struct handle_data)); if (!arg) { diff --git a/tests/rotctld.c b/tests/rotctld.c index 04c9747ca..3c94aa54d 100644 --- a/tests/rotctld.c +++ b/tests/rotctld.c @@ -34,6 +34,7 @@ #include #include +#include #include /* See NOTES */ @@ -160,6 +161,12 @@ int main(int argc, char *argv[]) char host[NI_MAXHOST]; char serv[NI_MAXSERV]; +#ifdef HAVE_PTHREAD + pthread_t thread; + pthread_attr_t attr; +#endif + struct handle_data *arg; + while (1) { int c; int option_index = 0; @@ -416,16 +423,29 @@ int main(int argc, char *argv[]) exit(1); } +#ifdef SIGPIPE + /* Ignore SIGPIPE as we will handle it at the write()/send() calls + that will consequently fail with EPIPE. All child threads will + inherit this disposition which is what we want. */ +#if HAVE_SIGACTION + struct sigaction act; + memset (&act, 0, sizeof act); + act.sa_handler = SIG_IGN; + act.sa_flags = SA_RESTART; + if (sigaction (SIGPIPE, &act, NULL)) { + handle_error (RIG_DEBUG_ERR, "sigaction"); + } +#elif HAVE_SIGNAL + if (SIG_ERR == signal (SIGPIPE, SIG_IGN))) + handle_error (RIG_DEBUG_ERR, "signal"); + } +#endif +#endif + /* * main loop accepting connections */ do { -#ifdef HAVE_PTHREAD - pthread_t thread; - pthread_attr_t attr; -#endif - struct handle_data *arg; - arg = malloc(sizeof(struct handle_data)); if (!arg) {