]> git.ipfire.org Git - thirdparty/curl.git/commitdiff
servers: fix to reverse `SA_RESTART` option for `sigaction()` on modern codepath master
authorViktor Szakats <commit@vsz.me>
Tue, 16 Jun 2026 01:07:58 +0000 (03:07 +0200)
committerViktor Szakats <commit@vsz.me>
Tue, 4 Aug 2026 15:36:14 +0000 (17:36 +0200)
Historically servers used the deprecated `siginterrupt()` function to
configure restart behavior on specific signals. It accepts a flag, where
1 means to remove the `SA_RESTART` option, and 0 means to enable it.

In year 2021 3fb6e5a01001b8c7dfdc33a89041178aac381a27 introduced the
modern alternative to the codebase, replacing `siginterrupt()` with
`sigaction()`. After this patch, supporting, modern, systems reacted on
the same flag, but, by accident, set the `SA_RESTART` bit when flag is
1, and did not set it when 0. This reversed the previous behavior, and
the one still used on the `siginterrupt()` legacy codepath.

Fix it by revesring the `SA_RESTART` logic for the `sigaction()`
codepath, syncing it with the pre-existing behavior.

I find it odd this did not cause any perceivable issue for 5 years, even
though it's the active one in most Unix envs.

Spotted by GitHub Code Quality, though suggesting to fix
`siginterrupt()` calls. But looking into the history, those were correct
all along.

Refs:
https://pubs.opengroup.org/onlinepubs/9699919799/functions/siginterrupt.html
https://pubs.opengroup.org/onlinepubs/9699919799/functions/sigaction.html
https://www.man7.org/linux/man-pages/man3/siginterrupt.3.html
https://www.man7.org/linux/man-pages/man2/sigaction.2.html

Follow-up to 3fb6e5a01001b8c7dfdc33a89041178aac381a27 #6529

Closes #22037

tests/server/util.c

index 805f615f4cb858d927495a30a9868eb2d1c6539b..2bb5b3f96df0bc30c1f4c5f61eac558a13a772e5 100644 (file)
@@ -555,8 +555,7 @@ static DWORD WINAPI main_window_loop(void *lpParameter)
 }
 #endif
 
-static SIGHANDLER_T set_signal(int signum, SIGHANDLER_T handler,
-                               bool restartable)
+static SIGHANDLER_T set_signal(int signum, SIGHANDLER_T handler, int norestart)
 {
 #if defined(HAVE_SIGACTION) && defined(SA_RESTART)
   struct sigaction sa, oldsa;
@@ -565,7 +564,7 @@ static SIGHANDLER_T set_signal(int signum, SIGHANDLER_T handler,
   sa.sa_handler = handler;
   sigemptyset(&sa.sa_mask);
   sigaddset(&sa.sa_mask, signum);
-  sa.sa_flags = restartable ? SA_RESTART : 0;
+  sa.sa_flags = norestart ? 0 : SA_RESTART;
 
   if(sigaction(signum, &sa, &oldsa))
     return SIG_ERR;
@@ -576,9 +575,9 @@ static SIGHANDLER_T set_signal(int signum, SIGHANDLER_T handler,
 
 #ifdef HAVE_SIGINTERRUPT
   if(oldhdlr != SIG_ERR)
-    siginterrupt(signum, (int)restartable);
+    siginterrupt(signum, norestart);
 #else
-  (void)restartable;
+  (void)norestart;
 #endif
 
   return oldhdlr;
@@ -597,14 +596,14 @@ void install_signal_handlers(bool keep_sigalrm)
 #endif
 #ifdef SIGHUP
   /* ignore SIGHUP signal */
-  old_sighup_handler = set_signal(SIGHUP, SIG_IGN, FALSE);
+  old_sighup_handler = set_signal(SIGHUP, SIG_IGN, 0);
   if(old_sighup_handler == SIG_ERR)
     logmsg("cannot install SIGHUP handler: (%d) %s",
            errno, curlx_strerror(errno, errbuf, sizeof(errbuf)));
 #endif
 #ifdef SIGPIPE
   /* ignore SIGPIPE signal */
-  old_sigpipe_handler = set_signal(SIGPIPE, SIG_IGN, FALSE);
+  old_sigpipe_handler = set_signal(SIGPIPE, SIG_IGN, 0);
   if(old_sigpipe_handler == SIG_ERR)
     logmsg("cannot install SIGPIPE handler: (%d) %s",
            errno, curlx_strerror(errno, errbuf, sizeof(errbuf)));
@@ -612,7 +611,7 @@ void install_signal_handlers(bool keep_sigalrm)
 #ifdef SIGALRM
   if(!keep_sigalrm) {
     /* ignore SIGALRM signal */
-    old_sigalrm_handler = set_signal(SIGALRM, SIG_IGN, FALSE);
+    old_sigalrm_handler = set_signal(SIGALRM, SIG_IGN, 0);
     if(old_sigalrm_handler == SIG_ERR)
       logmsg("cannot install SIGALRM handler: (%d) %s",
              errno, curlx_strerror(errno, errbuf, sizeof(errbuf)));
@@ -622,21 +621,21 @@ void install_signal_handlers(bool keep_sigalrm)
 #endif
 #ifdef SIGINT
   /* handle SIGINT signal with our exit_signal_handler */
-  old_sigint_handler = set_signal(SIGINT, exit_signal_handler, TRUE);
+  old_sigint_handler = set_signal(SIGINT, exit_signal_handler, 1);
   if(old_sigint_handler == SIG_ERR)
     logmsg("cannot install SIGINT handler: (%d) %s",
            errno, curlx_strerror(errno, errbuf, sizeof(errbuf)));
 #endif
 #ifdef SIGTERM
   /* handle SIGTERM signal with our exit_signal_handler */
-  old_sigterm_handler = set_signal(SIGTERM, exit_signal_handler, TRUE);
+  old_sigterm_handler = set_signal(SIGTERM, exit_signal_handler, 1);
   if(old_sigterm_handler == SIG_ERR)
     logmsg("cannot install SIGTERM handler: (%d) %s",
            errno, curlx_strerror(errno, errbuf, sizeof(errbuf)));
 #endif
 #if defined(SIGBREAK) && defined(_WIN32)
   /* handle SIGBREAK signal with our exit_signal_handler */
-  old_sigbreak_handler = set_signal(SIGBREAK, exit_signal_handler, TRUE);
+  old_sigbreak_handler = set_signal(SIGBREAK, exit_signal_handler, 1);
   if(old_sigbreak_handler == SIG_ERR)
     logmsg("cannot install SIGBREAK handler: (%d) %s",
            errno, curlx_strerror(errno, errbuf, sizeof(errbuf)));
@@ -658,31 +657,31 @@ void restore_signal_handlers(bool keep_sigalrm)
 {
 #ifdef SIGHUP
   if(old_sighup_handler != SIG_ERR)
-    (void)set_signal(SIGHUP, old_sighup_handler, FALSE);
+    (void)set_signal(SIGHUP, old_sighup_handler, 0);
 #endif
 #ifdef SIGPIPE
   if(old_sigpipe_handler != SIG_ERR)
-    (void)set_signal(SIGPIPE, old_sigpipe_handler, FALSE);
+    (void)set_signal(SIGPIPE, old_sigpipe_handler, 0);
 #endif
 #ifdef SIGALRM
   if(!keep_sigalrm) {
     if(old_sigalrm_handler != SIG_ERR)
-      (void)set_signal(SIGALRM, old_sigalrm_handler, FALSE);
+      (void)set_signal(SIGALRM, old_sigalrm_handler, 0);
   }
 #else
   (void)keep_sigalrm;
 #endif
 #ifdef SIGINT
   if(old_sigint_handler != SIG_ERR)
-    (void)set_signal(SIGINT, old_sigint_handler, FALSE);
+    (void)set_signal(SIGINT, old_sigint_handler, 0);
 #endif
 #ifdef SIGTERM
   if(old_sigterm_handler != SIG_ERR)
-    (void)set_signal(SIGTERM, old_sigterm_handler, FALSE);
+    (void)set_signal(SIGTERM, old_sigterm_handler, 0);
 #endif
 #if defined(SIGBREAK) && defined(_WIN32)
   if(old_sigbreak_handler != SIG_ERR)
-    (void)set_signal(SIGBREAK, old_sigbreak_handler, FALSE);
+    (void)set_signal(SIGBREAK, old_sigbreak_handler, 0);
 #endif
 #ifdef _WIN32
   (void)SetConsoleCtrlHandler(ctrl_event_handler, FALSE);