xref: /netbsd-src/external/gpl3/gdb/dist/gdbsupport/signals-state-save-restore.cc (revision 5ba1f45f2a09259cc846f20c7c5501604d633c90)
1*5ba1f45fSchristos /* Copyright (C) 2016-2024 Free Software Foundation, Inc.
28dffb485Schristos 
38dffb485Schristos    This file is part of GDB.
48dffb485Schristos 
58dffb485Schristos    This program is free software; you can redistribute it and/or modify
68dffb485Schristos    it under the terms of the GNU General Public License as published by
78dffb485Schristos    the Free Software Foundation; either version 3 of the License, or
88dffb485Schristos    (at your option) any later version.
98dffb485Schristos 
108dffb485Schristos    This program is distributed in the hope that it will be useful,
118dffb485Schristos    but WITHOUT ANY WARRANTY; without even the implied warranty of
128dffb485Schristos    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
138dffb485Schristos    GNU General Public License for more details.
148dffb485Schristos 
158dffb485Schristos    You should have received a copy of the GNU General Public License
168dffb485Schristos    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
178dffb485Schristos 
188dffb485Schristos #include "signals-state-save-restore.h"
198dffb485Schristos #include "gdbsupport/gdb-sigmask.h"
208dffb485Schristos 
218dffb485Schristos #include <signal.h>
228dffb485Schristos 
238dffb485Schristos /* The original signal actions and mask.  */
248dffb485Schristos 
258dffb485Schristos #ifdef HAVE_SIGACTION
268dffb485Schristos static struct sigaction original_signal_actions[NSIG];
278dffb485Schristos 
288dffb485Schristos static sigset_t original_signal_mask;
298dffb485Schristos #endif
308dffb485Schristos 
318dffb485Schristos /* See signals-state-save-restore.h.   */
328dffb485Schristos 
338dffb485Schristos void
348dffb485Schristos save_original_signals_state (bool quiet)
358dffb485Schristos {
368dffb485Schristos #ifdef HAVE_SIGACTION
378dffb485Schristos   int i;
388dffb485Schristos   int res;
398dffb485Schristos 
408dffb485Schristos   res = gdb_sigmask (0,  NULL, &original_signal_mask);
418dffb485Schristos   if (res == -1)
428dffb485Schristos     perror_with_name (("sigprocmask"));
438dffb485Schristos 
448dffb485Schristos   bool found_preinstalled = false;
458dffb485Schristos 
468dffb485Schristos   for (i = 1; i < NSIG; i++)
478dffb485Schristos     {
488dffb485Schristos       struct sigaction *oldact = &original_signal_actions[i];
498dffb485Schristos 
508dffb485Schristos       res = sigaction (i, NULL, oldact);
518dffb485Schristos       if (res == -1 && errno == EINVAL)
528dffb485Schristos 	{
538dffb485Schristos 	  /* Some signal numbers in the range are invalid.  */
548dffb485Schristos 	  continue;
558dffb485Schristos 	}
568dffb485Schristos       else if (res == -1)
578dffb485Schristos 	perror_with_name (("sigaction"));
588dffb485Schristos 
598dffb485Schristos       /* If we find a custom signal handler already installed, then
608dffb485Schristos 	 this function was called too late.  This is a warning instead
618dffb485Schristos 	 of an internal error because this can also happen if you
628dffb485Schristos 	 LD_PRELOAD a library that installs a signal handler early via
638dffb485Schristos 	 __attribute__((constructor)), like libSegFault.so.  */
648dffb485Schristos       if (!quiet
658dffb485Schristos 	  && oldact->sa_handler != SIG_DFL
668dffb485Schristos 	  && oldact->sa_handler != SIG_IGN)
678dffb485Schristos 	{
688dffb485Schristos 	  found_preinstalled = true;
698dffb485Schristos 
708dffb485Schristos 	  /* Use raw fprintf here because we're being called in early
718dffb485Schristos 	     startup, before GDB's filtered streams are created.  */
728dffb485Schristos 	  fprintf (stderr,
738dffb485Schristos 		   _("warning: Found custom handler for signal "
748dffb485Schristos 		     "%d (%s) preinstalled.\n"), i,
758dffb485Schristos 		   strsignal (i));
768dffb485Schristos 	}
778dffb485Schristos     }
788dffb485Schristos 
798dffb485Schristos   if (found_preinstalled)
808dffb485Schristos     {
818dffb485Schristos       fprintf (stderr, _("\
828dffb485Schristos Some signal dispositions inherited from the environment (SIG_DFL/SIG_IGN)\n\
838dffb485Schristos won't be propagated to spawned programs.\n"));
848dffb485Schristos     }
858dffb485Schristos #endif
868dffb485Schristos }
878dffb485Schristos 
888dffb485Schristos /* See signals-state-save-restore.h.   */
898dffb485Schristos 
908dffb485Schristos void
918dffb485Schristos restore_original_signals_state (void)
928dffb485Schristos {
938dffb485Schristos #ifdef HAVE_SIGACTION
948dffb485Schristos   int i;
958dffb485Schristos   int res;
968dffb485Schristos 
978dffb485Schristos   for (i = 1; i < NSIG; i++)
988dffb485Schristos     {
998dffb485Schristos       res = sigaction (i, &original_signal_actions[i], NULL);
1008dffb485Schristos       if (res == -1 && errno == EINVAL)
1018dffb485Schristos 	{
1028dffb485Schristos 	  /* Some signal numbers in the range are invalid.  */
1038dffb485Schristos 	  continue;
1048dffb485Schristos 	}
1058dffb485Schristos       else if (res == -1)
1068dffb485Schristos 	perror_with_name (("sigaction"));
1078dffb485Schristos     }
1088dffb485Schristos 
1098dffb485Schristos   res = gdb_sigmask (SIG_SETMASK,  &original_signal_mask, NULL);
1108dffb485Schristos   if (res == -1)
1118dffb485Schristos     perror_with_name (("sigprocmask"));
1128dffb485Schristos #endif
1138dffb485Schristos }
114