Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: Modified the CS

...

Code Block
bgColor#FFcccc
langcpp
#include <csignal>
 
static void sig_handler(int sig) {
  // Implementation details elided.
}

void f() {
  if (SIG_ERR == std::signal(SIGTERM, sig_handler)) {
    // Handle error
  }
}

...

Code Block
bgColor#ccccff
langcpp
#include <csignal>
 
extern "C" void sig_handler(int sig) {
  // Implementation details elided.
}

void f() {
  if (SIG_ERR == std::signal(SIGTERM, sig_handler)) {
    // Handle error
  }
}

...

Code Block
bgColor#FFcccc
langcpp
#include <csignal>

static void g() noexcept(false);

extern "C" void sig_handler(int sig) {
  try {
    g();
  } catch (...) {
    // Handle error
  }
}
 
void finstall_signal_handler() {
  if (SIG_ERR == std::signal(SIGTERM, sig_handler)) {
    // Handle error
  }
}

...

There is no compliant solution whereby g() can be called from the signal handler because it allows exceptions. Even if g() were implemented such that it handled all exceptions and was marked noexcept(true), it would still be noncompliant to call it from a signal handler because g() would still use a feature that is not a part of the common subset of C and C++ features allowed by a signal handler. Therefore, this compliant solution removes the call to g(): from the signal handler, and instead polls a variable of type volatile sig_atomic_t periodically; if the variable is set to 1 in the signal handler, then g() is called to respond to the signal.

Code Block
bgColor#ccccff
langcpp
#include <csignal>

volatile sig_atomic_t signal_flag = 0;
static void g() noexcept(false); // Not called

extern "C" void sig_handler(int sig) {
  // Implement g()'s behavior to the extent possible given
  // the constraints placed on a signal handler function.
}

void fsignal_flag = 1;
}

void f() {
  if (SIG_ERR == std::signal(SIGTERM, sig_handler)) {
    // Handle error
  }
}
 
// Called periodically to poll the signal flag.
void poll_signal_flag() {
  if (SIGsignal_ERRflag == std::signal(SIGTERM, sig_handler)) {
 1) {
    signal_flag = 0;
    try {
      g();
    } catch(...) {
      // Handle error
    }
  }
}

Risk Assessment

Failing to use a plain old function as a signal handler can result in implementation-defined behavior as well as undefined behavior. Given the number of features that exist in C++ that do not also exist in C, the consequences that arise from failure to comply with this rule can range from benign (harmless) behavior to abnormal program termination, or even arbitrary code execution.

...