xref: /netbsd-src/external/gpl3/gdb/dist/gdbsupport/signals-state-save-restore.cc (revision 5ba1f45f2a09259cc846f20c7c5501604d633c90)
1 /* Copyright (C) 2016-2024 Free Software Foundation, Inc.
2 
3    This file is part of GDB.
4 
5    This program is free software; you can redistribute it and/or modify
6    it under the terms of the GNU General Public License as published by
7    the Free Software Foundation; either version 3 of the License, or
8    (at your option) any later version.
9 
10    This program is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13    GNU General Public License for more details.
14 
15    You should have received a copy of the GNU General Public License
16    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
17 
18 #include "signals-state-save-restore.h"
19 #include "gdbsupport/gdb-sigmask.h"
20 
21 #include <signal.h>
22 
23 /* The original signal actions and mask.  */
24 
25 #ifdef HAVE_SIGACTION
26 static struct sigaction original_signal_actions[NSIG];
27 
28 static sigset_t original_signal_mask;
29 #endif
30 
31 /* See signals-state-save-restore.h.   */
32 
33 void
34 save_original_signals_state (bool quiet)
35 {
36 #ifdef HAVE_SIGACTION
37   int i;
38   int res;
39 
40   res = gdb_sigmask (0,  NULL, &original_signal_mask);
41   if (res == -1)
42     perror_with_name (("sigprocmask"));
43 
44   bool found_preinstalled = false;
45 
46   for (i = 1; i < NSIG; i++)
47     {
48       struct sigaction *oldact = &original_signal_actions[i];
49 
50       res = sigaction (i, NULL, oldact);
51       if (res == -1 && errno == EINVAL)
52 	{
53 	  /* Some signal numbers in the range are invalid.  */
54 	  continue;
55 	}
56       else if (res == -1)
57 	perror_with_name (("sigaction"));
58 
59       /* If we find a custom signal handler already installed, then
60 	 this function was called too late.  This is a warning instead
61 	 of an internal error because this can also happen if you
62 	 LD_PRELOAD a library that installs a signal handler early via
63 	 __attribute__((constructor)), like libSegFault.so.  */
64       if (!quiet
65 	  && oldact->sa_handler != SIG_DFL
66 	  && oldact->sa_handler != SIG_IGN)
67 	{
68 	  found_preinstalled = true;
69 
70 	  /* Use raw fprintf here because we're being called in early
71 	     startup, before GDB's filtered streams are created.  */
72 	  fprintf (stderr,
73 		   _("warning: Found custom handler for signal "
74 		     "%d (%s) preinstalled.\n"), i,
75 		   strsignal (i));
76 	}
77     }
78 
79   if (found_preinstalled)
80     {
81       fprintf (stderr, _("\
82 Some signal dispositions inherited from the environment (SIG_DFL/SIG_IGN)\n\
83 won't be propagated to spawned programs.\n"));
84     }
85 #endif
86 }
87 
88 /* See signals-state-save-restore.h.   */
89 
90 void
91 restore_original_signals_state (void)
92 {
93 #ifdef HAVE_SIGACTION
94   int i;
95   int res;
96 
97   for (i = 1; i < NSIG; i++)
98     {
99       res = sigaction (i, &original_signal_actions[i], NULL);
100       if (res == -1 && errno == EINVAL)
101 	{
102 	  /* Some signal numbers in the range are invalid.  */
103 	  continue;
104 	}
105       else if (res == -1)
106 	perror_with_name (("sigaction"));
107     }
108 
109   res = gdb_sigmask (SIG_SETMASK,  &original_signal_mask, NULL);
110   if (res == -1)
111     perror_with_name (("sigprocmask"));
112 #endif
113 }
114