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
This commit is contained in:
Stefan Eissing 2026-01-20 11:09:58 +01:00 committed by Daniel Stenberg
parent 0bef137fbd
commit 3dd7f5890f
No known key found for this signature in database
GPG key ID: 5CC908FDB71E12C2
5 changed files with 31 additions and 33 deletions

View file

@ -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);