]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
ada: Disable signals when calling pthread_create on QNX
authorJohannes Kliemann <kliemann@adacore.com>
Wed, 9 Jul 2025 15:40:55 +0000 (17:40 +0200)
committerMarc Poulhiès <dkm@gcc.gnu.org>
Thu, 11 Sep 2025 09:10:47 +0000 (11:10 +0200)
The QNX Certified Products Defect Notification from February 2025
mentions a potential memory leak when pthread_create is interrupted by a
signal. It recommends to disable signals for this function call.

gcc/ada/ChangeLog:

* adaint.c: Add functions to disable and enable signals on QNX.
* libgnarl/s-taprop__qnx.adb (Create_Task): Disable
signals when calling pthread_create.

gcc/ada/adaint.c
gcc/ada/libgnarl/s-taprop__qnx.adb

index adc39517280a8120359a24bd816a80ba49d72237..7b78d91e0e72f10ead77bc8d4f9c08a359467541 100644 (file)
 #ifdef __QNX__
 #include <sys/syspage.h>
 #include <sys/time.h>
+#include <signal.h>
 #endif
 
 #ifdef IN_RTS
@@ -3719,6 +3720,68 @@ void __gnat_killprocesstree (int pid, int sig_num)
   */
 }
 
+#if defined (__QNX__)
+
+static __thread sigset_t set;
+static __thread sigset_t oset;
+static __thread int signals_disabled = 0;
+
+int __gnat_disable_signals(void)
+{
+    sigemptyset(&set);
+    sigaddset(&set, SIGHUP);
+    sigaddset(&set, SIGINT);
+    sigaddset(&set, SIGQUIT);
+    sigaddset(&set, SIGILL);
+    sigaddset(&set, SIGTRAP);
+    sigaddset(&set, SIGIOT);
+    sigaddset(&set, SIGABRT);
+    sigaddset(&set, SIGEMT);
+    sigaddset(&set, SIGDEADLK);
+    sigaddset(&set, SIGFPE);
+    sigaddset(&set, SIGKILL);
+    sigaddset(&set, SIGBUS);
+    sigaddset(&set, SIGSEGV);
+    sigaddset(&set, SIGSYS);
+    sigaddset(&set, SIGPIPE);
+    sigaddset(&set, SIGALRM);
+    sigaddset(&set, SIGTERM);
+    sigaddset(&set, SIGUSR1);
+    sigaddset(&set, SIGUSR2);
+    sigaddset(&set, SIGCHLD);
+    sigaddset(&set, SIGCLD);
+    sigaddset(&set, SIGPWR);
+    sigaddset(&set, SIGWINCH);
+    sigaddset(&set, SIGURG);
+    sigaddset(&set, SIGPOLL);
+    sigaddset(&set, SIGIO);
+    sigaddset(&set, SIGSTOP);
+    sigaddset(&set, SIGTSTP);
+    sigaddset(&set, SIGCONT);
+    sigaddset(&set, SIGTTIN);
+    sigaddset(&set, SIGTTOU);
+    sigaddset(&set, SIGVTALRM);
+    sigaddset(&set, SIGPROF);
+    sigaddset(&set, SIGXCPU);
+    sigaddset(&set, SIGXFSZ);
+    sigaddset(&set, SIGDOOM);
+
+    int ret = sigprocmask(SIG_BLOCK, &set, &oset);
+    signals_disabled = !ret;
+    return ret;
+}
+
+int __gnat_enable_signals(void)
+{
+    if (!signals_disabled) {
+        return 0;
+    }
+    signals_disabled = 0;
+    return sigprocmask(SIG_SETMASK, &oset, 0);
+}
+
+#endif
+
 #ifdef __cplusplus
 }
 #endif
index e7d245fec7dea8e81162e5016720a67961be97cd..b51f2b527082e058f93488b60359607e9aac67f8 100644 (file)
@@ -766,6 +766,16 @@ package body System.Task_Primitives.Operations is
       function Thread_Body_Access is new
         Ada.Unchecked_Conversion (System.Address, Thread_Body);
 
+      function Disable_Signals return Interfaces.C.int with
+        Import,
+        Convention    => C,
+        External_Name => "__gnat_disable_signals";
+
+      function Enable_Signals return Interfaces.C.int with
+        Import,
+        Convention    => C,
+        External_Name => "__gnat_enable_signals";
+
    begin
       Adjusted_Stack_Size :=
          Interfaces.C.size_t (Stack_Size + Alternate_Stack_Size);
@@ -840,10 +850,11 @@ package body System.Task_Primitives.Operations is
 
       pragma Assert (Result = 0);
 
-      --  Since the initial signal mask of a thread is inherited from the
-      --  creator, and the Environment task has all its signals masked, we
-      --  do not need to manipulate caller's signal mask at this point.
-      --  All tasks in RTS will have All_Tasks_Mask initially.
+      --  (QMS3263) lists PR 2894086. This defect causes a memory leak when
+      --  pthread_create is interrupted by a signal and later resumed. To avoid
+      --  avoid such a leak the document suggests to disable signals while
+      --  calling pthread_create. The signal mask of the calling thread is
+      --  restored after the call to pthread_create.
 
       --  The write to T.Common.LL.Thread is not racy with regard to the
       --  created thread because the created thread will not access it until
@@ -851,6 +862,8 @@ package body System.Task_Primitives.Operations is
       --  Restricted.Stages is used). One can verify that by inspecting the
       --  Task_Wrapper procedures.
 
+      Result := Disable_Signals;
+      pragma Assert (Result = 0);
       Result := pthread_create
         (T.Common.LL.Thread'Access,
          Attributes'Access,
@@ -860,6 +873,9 @@ package body System.Task_Primitives.Operations is
 
       Succeeded := Result = 0;
 
+      Result := Enable_Signals;
+      pragma Assert (Result = 0);
+
       Result := pthread_attr_destroy (Attributes'Access);
       pragma Assert (Result = 0);
    end Create_Task;