From 7d80ed64e4351556d69dbfac73f5f579d5a9ebb2 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Mon, 11 Mar 2013 00:39:52 +0100 Subject: [PATCH] SIGPIPE: ignored while inside the library MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ... and restore the ordinary handling again when it returns. This is done for curl_easy_perform() and curl_easy_cleanup() only for now - and only when built to use OpenSSL as backend as this is the known culprit for the spurious SIGPIPEs people have received. Bug: http://curl.haxx.se/bug/view.cgi?id=1180 Reported by: LluĂ­s Batlle i Rossell --- lib/easy.c | 56 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+) diff --git a/lib/easy.c b/lib/easy.c index 94a84abb2..32a887657 100644 --- a/lib/easy.c +++ b/lib/easy.c @@ -50,6 +50,11 @@ #include #endif +#if defined(HAVE_SIGNAL_H) && defined(HAVE_SIGACTION) && defined(USE_OPENSSL) +#define SIGPIPE_IGNORE 1 +#include +#endif + #include "strequal.h" #include "urldata.h" #include @@ -81,6 +86,49 @@ /* The last #include file should be: */ #include "memdebug.h" +#ifdef SIGPIPE_IGNORE +#define SIGPIPE_VARIABLE(x) struct sigaction x + +/* + * sigpipe_ignore() makes sure we ignore SIGPIPE while running libcurl + * internals, and then sigpipe_restore() will restore the situation when we + * return from libcurl again. + */ +static void sigpipe_ignore(struct SessionHandle *data, + struct sigaction *pipe) +{ + if(!data->set.no_signal) { + struct sigaction action; + /* first, extract the existing situation */ + sigaction(SIGPIPE, NULL, pipe); + action = *pipe; + /* ignore this signal */ + action.sa_handler = SIG_IGN; + sigaction(SIGPIPE, &action, NULL); + } +} + +/* + * sigpipe_restore() puts back the outside world's opinion of signal handler + * and SIGPIPE handling. It MUST only be called after a corresponding + * sigpipe_ignore() was used. + */ +static void sigpipe_restore(struct SessionHandle *data, + struct sigaction *pipe) +{ + if(!data->set.no_signal) { + /* restore the outside state */ + sigaction(SIGPIPE, pipe, NULL); + } +} + +#else +/* for systems without sigaction */ +#define sigpipe_ignore(x,y) +#define sigpipe_restore(x,y) +#define SIGPIPE_VARIABLE(x) +#endif + /* win32_cleanup() is for win32 socket cleanup functionality, the opposite of win32_init() */ static void win32_cleanup(void) @@ -423,6 +471,7 @@ CURLcode curl_easy_perform(CURL *easy) int without_fds = 0; /* count number of consecutive returns from curl_multi_wait() without any filedescriptors */ struct timeval before; + SIGPIPE_VARIABLE(pipe); if(!easy) return CURLE_BAD_FUNCTION_ARGUMENT; @@ -455,6 +504,8 @@ CURLcode curl_easy_perform(CURL *easy) return CURLE_FAILED_INIT; } + sigpipe_ignore(data, &pipe); + /* assign this after curl_multi_add_handle() since that function checks for it and rejects this handle otherwise */ data->multi = multi; @@ -511,6 +562,8 @@ CURLcode curl_easy_perform(CURL *easy) a failure here, room for future improvement! */ (void)curl_multi_remove_handle(multi, easy); + sigpipe_restore(data, &pipe); + /* The multi handle is kept alive, owned by the easy handle */ return code; } @@ -522,11 +575,14 @@ CURLcode curl_easy_perform(CURL *easy) void curl_easy_cleanup(CURL *curl) { struct SessionHandle *data = (struct SessionHandle *)curl; + SIGPIPE_VARIABLE(pipe); if(!data) return; + sigpipe_ignore(data, &pipe); Curl_close(data); + sigpipe_restore(data, &pipe); } /*