kicad/thirdparty/sentry-native/external/crashpad/util/posix/signals.h

247 lines
11 KiB
C++
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// Copyright 2017 The Crashpad Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef CRASHPAD_UTIL_POSIX_SIGNALS_H_
#define CRASHPAD_UTIL_POSIX_SIGNALS_H_
#include <signal.h>
#include <set>
namespace crashpad {
//! \brief Utilities for handling POSIX signals.
class Signals {
public:
//! \brief A signal number used by Crashpad to simulate signals.
static constexpr int kSimulatedSigno = -1;
//! \brief The type used for `struct sigaction::sa_sigaction`.
using Handler = void (*)(int, siginfo_t*, void*);
//! \brief A group of `struct sigaction` structures corresponding to a set
//! of signals previous actions, addressable by signal number.
//!
//! This type is used to store previous signal actions when new actions are
//! installed in batch by InstallCrashHandlers() or
//! InstallTerminateHandlers().
//!
//! This object is not initialized by any constructor. Its expected initial
//! state is to have its contents filled with zeroes. Because signal handlers
//! are stateless (there is no “context” parameter), any state must be
//! accessed via objects of static storage duration, and it is expected that
//! objects of this class will only ever exist with static storage duration,
//! which in the absence of a constructor will be zero-initialized as
//! expected. In the event that an object of this class must exist with a
//! different storage duration, such as automatic or dynamic storage duration,
//! it must be explicitly initialized. For example: `OldActions old_actions =
//! {};`.
class OldActions {
public:
// DISALLOW_COPY_AND_ASSIGN removes the default constructor, so explicitly
// opt for it. This should not result in any static initialization code even
// when an object of this class is given static storage duration.
OldActions() = default;
OldActions(const OldActions&) = delete;
OldActions& operator=(const OldActions&) = delete;
//! \brief Returns a `struct sigaction` structure corresponding to the
//! given signal.
//!
//! \note This method is safe to call from a signal handler.
struct sigaction* ActionForSignal(int sig);
private:
// As a small storage optimization, dont waste any space on a slot for
// signal 0, because there is no signal 0.
struct sigaction actions_[NSIG - 1];
};
Signals() = delete;
Signals(const Signals&) = delete;
Signals& operator=(const Signals&) = delete;
//! \brief Installs a new signal handler.
//!
//! \param[in] sig The signal number to handle.
//! \param[in] handler A signal-handling function to execute, used as the
//! `struct sigaction::sa_sigaction` field when calling `sigaction()`.
//! \param[in] flags Flags to pass to `sigaction()` in the `struct
//! sigaction::sa_flags` field. `SA_SIGINFO` will be specified implicitly.
//! \param[out] old_action The previous action for the signal, replaced by the
//! new action. May be `nullptr` if not needed.
//!
//! \return `true` on success. `false` on failure with a message logged.
//!
//! \warning This function may not be called from a signal handler because of
//! its use of logging. See RestoreHandlerAndReraiseSignalOnReturn()
//! instead.
static bool InstallHandler(int sig,
Handler handler,
int flags,
struct sigaction* old_action);
//! \brief Installs `SIG_DFL` for the signal \a sig.
//!
//! \param[in] sig The signal to set the default action for.
//!
//! \return `true` on success, `false` on failure with errno set. No message
//! is logged.
static bool InstallDefaultHandler(int sig);
//! \brief Installs a new signal handler for all signals associated with
//! crashes.
//!
//! Signals associated with crashes are those whose default dispositions
//! involve creating a core dump. The precise set of signals involved varies
//! between operating systems.
//!
//! A single signal may either be associated with a crash or with termination
//! (see InstallTerminateHandlers()), and perhaps neither, but never both.
//!
//! \param[in] handler A signal-handling function to execute, used as the
//! `struct sigaction::sa_sigaction` field when calling `sigaction()`.
//! \param[in] flags Flags to pass to `sigaction()` in the `struct
//! sigaction::sa_flags` field. `SA_SIGINFO` will be specified implicitly.
//! \param[out] old_actions The previous actions for the signals, replaced by
//! the new action. May be `nullptr` if not needed. The same \a
//! old_actions object may be used for calls to both this function and
//! InstallTerminateHandlers().
//! \param[in] unhandled_signals Signal handlers will not be installed for
//! signal numbers in this set. Optional.
//!
//! \return `true` on success. `false` on failure with a message logged.
//!
//! \warning This function may not be called from a signal handler because of
//! its use of logging. See RestoreHandlerAndReraiseSignalOnReturn()
//! instead.
static bool InstallCrashHandlers(
Handler handler,
int flags,
OldActions* old_actions,
const std::set<int>* unhandled_signals = nullptr);
//! \brief Installs a new signal handler for all signals associated with
//! termination.
//!
//! Signals associated with termination are those whose default dispositions
//! involve terminating the process without creating a core dump. The precise
//! set of signals involved varies between operating systems.
//!
//! A single signal may either be associated with termination or with a
//! crash (see InstalCrashHandlers()), and perhaps neither, but never both.
//!
//! \param[in] handler A signal-handling function to execute, used as the
//! `struct sigaction::sa_sigaction` field when calling `sigaction()`.
//! \param[in] flags Flags to pass to `sigaction()` in the `struct
//! sigaction::sa_flags` field. `SA_SIGINFO` will be specified implicitly.
//! \param[out] old_actions The previous actions for the signals, replaced by
//! the new action. May be `nullptr` if not needed. The same \a
//! old_actions object may be used for calls to both this function and
//! InstallCrashHandlers().
//!
//! \return `true` on success. `false` on failure with a message logged.
//!
//! \warning This function may not be called from a signal handler because of
//! its use of logging. See RestoreHandlerAndReraiseSignalOnReturn()
//! instead.
static bool InstallTerminateHandlers(Handler handler,
int flags,
OldActions* old_actions);
//! \brief Determines whether a signal will be re-raised autonomously upon
//! return from a signal handler.
//!
//! Certain signals, when generated synchronously in response to a hardware
//! fault, are unrecoverable. Upon return from the signal handler, the same
//! action that triggered the signal to be raised initially will be retried,
//! and unless the signal handler took action to mitigate this error, the same
//! signal will be re-raised. As an example, a CPU will not be able to read
//! unmapped memory (causing `SIGSEGV`), thus the signal will be re-raised
//! upon return from the signal handler unless the signal handler established
//! a memory mapping where required.
//!
//! It is important to distinguish between these synchronous signals generated
//! in response to a hardware fault and signals generated asynchronously or in
//! software. As an example, `SIGSEGV` will not re-raise autonomously if sent
//! by `kill()`.
//!
//! This function distinguishes between signals that can re-raise
//! autonomously, and for those that can, between instances of the signal that
//! were generated synchronously in response to a hardware fault and instances
//! that were generated by other means.
//!
//! \param[in] siginfo A pointer to a `siginfo_t` object received by a signal
//! handler.
//!
//! \return `true` if the signal being handled will re-raise itself
//! autonomously upon return from a signal handler. `false` if it will
//! not. When this function returns `false`, a signal can still be
//! re-raised upon return from a signal handler by calling `raise()` from
//! within the signal handler.
//!
//! \note This function is safe to call from a signal handler.
static bool WillSignalReraiseAutonomously(const siginfo_t* siginfo);
//! \brief Restores a previous signal action and arranges to re-raise a signal
//! on return from a signal handler.
//!
//! \param[in] siginfo A pointer to a `siginfo_t` object received by a signal
//! handler.
//! \param[in] old_action The previous action for the signal, which will be
//! re-established as the signals action. May be `nullptr`, which directs
//! the default action for the signal to be used.
//!
//! If this function fails, it will immediately call `_exit()` and set an exit
//! status of `191`.
//!
//! \note This function may only be called from a signal handler.
static void RestoreHandlerAndReraiseSignalOnReturn(
const siginfo_t* siginfo,
const struct sigaction* old_action);
//! \brief Determines whether a signal is associated with a crash.
//!
//! Signals associated with crashes are those whose default dispositions
//! involve creating a core dump. The precise set of signals involved varies
//! between operating systems.
//!
//! \param[in] sig The signal to test.
//!
//! \return `true` if \a sig is associated with a crash. `false` otherwise.
//!
//! \note This function is safe to call from a signal handler.
static bool IsCrashSignal(int sig);
//! \brief Determines whether a signal is associated with termination.
//!
//! Signals associated with termination are those whose default dispositions
//! involve terminating the process without creating a core dump. The precise
//! set of signals involved varies between operating systems.
//!
//! \param[in] sig The signal to test.
//!
//! \return `true` if \a sig is associated with termination. `false`
//! otherwise.
//!
//! \note This function is safe to call from a signal handler.
static bool IsTerminateSignal(int sig);
};
} // namespace crashpad
#endif // CRASHPAD_UTIL_POSIX_SIGNALS_H_