From 357e401c43508b96d507b3b573eb2d83c0396975 Mon Sep 17 00:00:00 2001 From: Sergey Fedorov Date: Mon, 27 Jul 2026 15:35:05 +0000 Subject: [PATCH 10/10] client: use SO_NOSIGPIPE instead of MSG_NOSIGNAL on Darwin MSG_NOSIGNAL doesn't exist on Darwin (or Solaris). Rather than just defining it away as a no-op (which would leave send() free to raise SIGPIPE and kill footclient whenever the server-side connection drops mid-write, since client.c never ignores SIGPIPE itself), set SO_NOSIGPIPE on the socket once after creation -- Darwin/BSD's socket-option-level equivalent, which suppresses SIGPIPE for every send() on that fd rather than needing a per-call flag. Co-Authored-By: Claude Sonnet 5 Claude-Session: https://claude.ai/code/session_01U6fuL1PtRJHhr97gAGyS1h --- client.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/client.c b/client.c index befd3ab0..be18ce45 100644 --- a/client.c +++ b/client.c @@ -13,6 +13,11 @@ #include #include +#if !defined(MSG_NOSIGNAL) + /* Darwin: SIGPIPE is suppressed via SO_NOSIGPIPE on the socket instead. */ + #define MSG_NOSIGNAL 0 +#endif + #include #define LOG_MODULE "foot-client" @@ -363,6 +368,18 @@ main(int argc, char *const *argv) goto err; } +#if defined(__APPLE__) + /* + * Darwin has no MSG_NOSIGNAL send() flag (defined as a no-op + * below); use the SO_NOSIGPIPE socket option instead, which + * covers every send() on this fd, not just the ones passing the + * flag. + */ + int nosigpipe = 1; + if (setsockopt(fd, SOL_SOCKET, SO_NOSIGPIPE, &nosigpipe, sizeof(nosigpipe)) < 0) + LOG_ERRNO("failed to set SO_NOSIGPIPE on socket"); +#endif + struct sockaddr_un addr = {.sun_family = AF_UNIX}; if (server_socket_path != NULL) { -- 2.43.0