From: Stefan Eissing Date: Tue, 20 Jan 2026 10:09:58 +0000 (+0100) Subject: socket: check result of SO_NOSIGPIPE X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=3dd7f5890f2a4e85d8eaa31b9b44de153db6c597;p=thirdparty%2Fcurl.git socket: check result of SO_NOSIGPIPE New define USE_SO_NOSIGPIPE in curl_setup.h, for now set whenever SO_NOSIGPIPE is defined. Maybe overridden in the future on systems where this does not work. With USE_SO_NOSIGPIPE defined, set SO_NOSIGPIPE on all sockets created by libcurl and fail the creation when setsockopt() fails. Closes #20370 --- diff --git a/docs/libcurl/libcurl-env-dbg.md b/docs/libcurl/libcurl-env-dbg.md index ce6b480ae3..2cbf1c7bcb 100644 --- a/docs/libcurl/libcurl-env-dbg.md +++ b/docs/libcurl/libcurl-env-dbg.md @@ -107,6 +107,11 @@ A fixed faked value to use instead of a proper random number so that functions in libcurl that are otherwise getting random outputs can be tested for what they generate. +## `CURL_SIGPIPE_DEBUG` + +When present, `curl` does not set `SIGPIPE` to ignore. This allows +verification that `libcurl` does not cause `SIGPIPE` to be raised. + ## `CURL_SMALLREQSEND` An alternative size of HTTP data to be sent at a time only if smaller than the diff --git a/lib/cf-socket.c b/lib/cf-socket.c index 17b1a47870..c1863d17de 100644 --- a/lib/cf-socket.c +++ b/lib/cf-socket.c @@ -97,32 +97,6 @@ static void tcpnodelay(struct Curl_cfilter *cf, #endif } -#ifdef SO_NOSIGPIPE -/* The preferred method on macOS (10.2 and later) to prevent SIGPIPEs when - sending data to a dead peer (instead of relying on the 4th argument to send - being MSG_NOSIGNAL). Possibly also existing and in use on other BSD - systems? */ -static void nosigpipe(struct Curl_cfilter *cf, - struct Curl_easy *data, - curl_socket_t sockfd) -{ - int onoff = 1; - if(setsockopt(sockfd, SOL_SOCKET, SO_NOSIGPIPE, - (void *)&onoff, sizeof(onoff)) < 0) { -#ifndef CURL_DISABLE_VERBOSE_STRINGS - char buffer[STRERROR_LEN]; - CURL_TRC_CF(data, cf, "Could not set SO_NOSIGPIPE: %s", - curlx_strerror(SOCKERRNO, buffer, sizeof(buffer))); -#else - (void)cf; - (void)data; -#endif - } -} -#else -#define nosigpipe(x, y, z) Curl_nop_stmt -#endif - #if defined(USE_WINSOCK) || \ (defined(__sun) && !defined(TCP_KEEPIDLE)) || \ (defined(__DragonFly__) && __DragonFly_version < 500702) || \ @@ -358,6 +332,19 @@ static CURLcode socket_open(struct Curl_easy *data, return CURLE_COULDNT_CONNECT; } +#ifdef USE_SO_NOSIGPIPE + { + int onoff = 1; + if(setsockopt(*sockfd, SOL_SOCKET, SO_NOSIGPIPE, + (void *)&onoff, sizeof(onoff)) < 0) { + failf(data, "setsockopt enable SO_NOSIGPIPE: %s", + curlx_strerror(SOCKERRNO, errbuf, sizeof(errbuf))); + *sockfd = CURL_SOCKET_BAD; + return CURLE_COULDNT_CONNECT; + } + } +#endif /* USE_SO_NOSIGPIPE */ + #ifdef HAVE_FCNTL if(fcntl(*sockfd, F_SETFD, FD_CLOEXEC) < 0) { failf(data, "fcntl set CLOEXEC: %s", @@ -1101,8 +1088,6 @@ static CURLcode cf_socket_open(struct Curl_cfilter *cf, if(is_tcp && data->set.tcp_nodelay) tcpnodelay(cf, data, ctx->sock); - nosigpipe(cf, data, ctx->sock); - if(is_tcp && data->set.tcp_keepalive) tcpkeepalive(cf, data, ctx->sock); diff --git a/lib/curl_setup.h b/lib/curl_setup.h index ff991a074b..750ba90d2d 100644 --- a/lib/curl_setup.h +++ b/lib/curl_setup.h @@ -453,6 +453,10 @@ #define USE_EVENTFD #endif +#ifdef SO_NOSIGPIPE +#define USE_SO_NOSIGPIPE +#endif + #include #include diff --git a/lib/sigpipe.h b/lib/sigpipe.h index 9fe13af92b..a906b27037 100644 --- a/lib/sigpipe.h +++ b/lib/sigpipe.h @@ -25,8 +25,7 @@ ***************************************************************************/ #include "curl_setup.h" -#if defined(HAVE_SIGACTION) && \ - (defined(USE_OPENSSL) || defined(USE_MBEDTLS) || defined(USE_WOLFSSL)) +#if defined(HAVE_SIGACTION) && !defined(USE_SO_NOSIGPIPE) #include struct Curl_sigpipe_ctx { @@ -58,8 +57,10 @@ static CURL_INLINE void sigpipe_ignore(struct Curl_easy *data, action = ig->old_pipe_act; /* ignore this signal */ action.sa_handler = SIG_IGN; +#ifdef SA_SIGINFO /* clear SA_SIGINFO flag since we are using sa_handler */ action.sa_flags &= ~SA_SIGINFO; +#endif sigaction(SIGPIPE, &action, NULL); } } @@ -85,8 +86,8 @@ static CURL_INLINE void sigpipe_apply(struct Curl_easy *data, } } -#else -/* for systems without sigaction */ +#else /* !HAVE_SIGACTION || USE_SO_NOSIGPIPE */ +/* for systems without sigaction or where SO_NOSIGPIPE is used. */ #define sigpipe_ignore(x, y) do { (void)x; (void)y; } while(0) #define sigpipe_apply(x, y) do { (void)x; (void)y; } while(0) #define sigpipe_init(x) do { (void)x; } while(0) @@ -96,6 +97,6 @@ struct Curl_sigpipe_ctx { bool dummy; }; -#endif +#endif /* else HAVE_SIGACTION && !USE_SO_NOSIGPIPE */ #endif /* HEADER_CURL_SIGPIPE_H */ diff --git a/src/tool_main.c b/src/tool_main.c index 806fbd4c0e..bb17d046b4 100644 --- a/src/tool_main.c +++ b/src/tool_main.c @@ -172,6 +172,9 @@ int main(int argc, char *argv[]) } #if defined(HAVE_SIGNAL) && defined(SIGPIPE) +#ifdef DEBUGBUILD + if(!curl_getenv("CURL_SIGPIPE_DEBUG")) +#endif (void)signal(SIGPIPE, SIG_IGN); #endif