#include "guile/guile.h"
#include <array>
#include "inferior.h"
+#include "gdbsupport/scoped_signal_handler.h"
static script_sourcer_func source_gdb_script;
static objfile_script_sourcer_func source_gdb_objfile_script;
}
\f
-/* RAII class used to temporarily return SIG to its default handler. */
-
-template<int SIG>
-struct scoped_default_signal
-{
- scoped_default_signal ()
- { m_old_sig_handler = signal (SIG, SIG_DFL); }
-
- ~scoped_default_signal ()
- { signal (SIG, m_old_sig_handler); }
-
- DISABLE_COPY_AND_ASSIGN (scoped_default_signal);
-
-private:
- /* The previous signal handler that needs to be restored. */
- sighandler_t m_old_sig_handler;
-};
-
-/* Class to temporarily return SIGINT to its default handler. */
-
-using scoped_default_sigint = scoped_default_signal<SIGINT>;
-
/* Functions that iterate over all extension languages.
These only iterate over external extension languages, not including
GDB's own extension/scripting language, unless otherwise indicated. */
if (extlang->ops != nullptr
&& extlang->ops->initialize != NULL)
{
- scoped_default_sigint set_sigint_to_default_handler;
+ scoped_signal_handler<SIGINT> set_sigint_to_default_handler (SIG_DFL);
extlang->ops->initialize (extlang);
}
}
#include "infrun.h"
#include "gdbsupport/gdb_unlinker.h"
#include "gdbsupport/byte-vector.h"
+#include "gdbsupport/scoped_signal_handler.h"
#include "async-event.h"
#include "top.h"
#include "valprint.h"
{
scoped_restore restore_operation_disable
= record_full_gdb_operation_disable_set ();
+ scoped_signal_handler<SIGINT> interrupt_handler (record_full_sig_handler);
if (record_debug)
gdb_printf (gdb_stdlog,
}
record_full_get_sig = 0;
- signal (SIGINT, record_full_sig_handler);
record_full_stop_reason = TARGET_STOPPED_BY_NO_REASON;
}
}
- signal (SIGINT, handle_sigint);
-
return inferior_ptid;
}
#include <ctype.h>
#include "gdbsupport/gdb_wait.h"
+#include "gdbsupport/scoped_signal_handler.h"
#include "event-top.h"
#include "gdbthread.h"
#include "fnmatch.h"
if (timeout > 0)
{
#ifdef SIGALRM
-#if defined (HAVE_SIGACTION) && defined (SA_RESTART)
- struct sigaction sa, old_sa;
-
- sa.sa_handler = sigalrm_handler;
- sigemptyset (&sa.sa_mask);
- sa.sa_flags = 0;
- sigaction (SIGALRM, &sa, &old_sa);
-#else
- sighandler_t ofunc;
-
- ofunc = signal (SIGALRM, sigalrm_handler);
-#endif
+ scoped_signal_handler<SIGALRM> alarm_restore (sigalrm_handler);
alarm (timeout);
#endif
#ifdef SIGALRM
alarm (0);
-#if defined (HAVE_SIGACTION) && defined (SA_RESTART)
- sigaction (SIGALRM, &old_sa, NULL);
-#else
- signal (SIGALRM, ofunc);
-#endif
#endif
}
else
--- /dev/null
+/* RAII class to install a separate handler for a given signal
+
+ Copyright (C) 2024 Free Software Foundation, Inc.
+
+ This file is part of GDB.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+#ifndef SCOPED_SIGNAL_HANDLER_H
+#define SCOPED_SIGNAL_HANDLER_H
+
+#include <signal.h>
+
+#undef HAVE_SIGACTION
+
+/* RAII class to set a signal handler for a scope, that will take care of
+ unsetting the handler when the scope is left.
+ This class will try to use sigaction whenever available, following the
+ recommendation on the man page for signal, and only fallback to signal
+ if necessary. */
+template <int SIG>
+class scoped_signal_handler
+{
+public:
+ scoped_signal_handler (sighandler_t handler)
+ {
+#if defined (HAVE_SIGACTION)
+ struct sigaction act;
+
+ act.sa_handler = handler;
+ sigemptyset (&act.sa_mask);
+ act.sa_flags = 0;
+ sigaction (SIG, &act, &m_prev_handler);
+#else
+ /* The return of the function call is the previous signal handler, or
+ SIG_ERR if the function doesn't succeed. */
+ m_prev_handler = signal (SIG, handler);
+ /* According to the GNU libc manual, the only way signal fails is if
+ the signum given is invalid, so we should be safe to assert. */
+ gdb_assert (m_prev_handler != SIG_ERR);
+#endif
+ }
+
+ ~scoped_signal_handler ()
+ {
+#if defined (HAVE_SIGACTION)
+ sigaction (SIG, &m_prev_handler, nullptr);
+#else
+ signal (SIG, m_prev_handler);
+#endif
+ }
+
+ DISABLE_COPY_AND_ASSIGN (scoped_signal_handler);
+private:
+#if defined (HAVE_SIGACTION)
+ struct sigaction m_prev_handler;
+#else
+ sighandler_t m_prev_handler;
+#endif
+};
+
+#endif /* SCOPED_SIGNAL_HANDLER_H */