C++에서 SIGABRT 신호 처리

Jinku Hu 2023년10월12일
  1. sigaction을 사용하여SIGABRT 신호 핸들러 등록
  2. 신호 처리기에서sig_atomic_t 변수 사용
C++에서 SIGABRT 신호 처리

이 기사에서는 C++에서SIGABRT 신호를 처리하는 방법에 대한 여러 방법을 보여줍니다.

sigaction을 사용하여SIGABRT 신호 핸들러 등록

Unix 기반 운영 체제는 한 프로그램이 다른 프로그램에 비동기 적으로 메시지를 보낼 수있는 메커니즘 인 신호라는 기능을 지원합니다. 신호는 일반적으로 프로그램을 중단해야하는 사용자 또는 운영 체제 프로세스에서 전송됩니다. 시그널 핸들러는 프로그램이 주어진 시그널을 받으면 호출되는 코드 섹션입니다. 프로그램 중단, 프로그램 중지 및 해당 기본 신호 처리기로 프로그램 계속과 같은 작업에 대한 몇 가지 표준 신호가 있습니다. 그러나 사용자는 이러한 신호 처리기 대부분을 사용자 정의 함수로 재정의 할 수 있으며 sigaction은이를 등록하는 함수입니다.

SIGABRT는 기본적으로 프로그램이 종료되는 신호 중 하나입니다. 다음 코드 예제에서는 신호 핸들러를 재정의하고 신호가 수신되면 호출 할 정의 된 함수 (cleanupRoutine)를 할당합니다.

처음에struct sigaction 유형 객체는memset 함수 호출로 선언하고 초기화해야합니다.

다음으로 데이터 멤버 sa_handler에 호출해야하는 함수의 주소를 할당해야합니다.

그런 다음 SIGABRT핸들러를 방해하지 않도록 다른 신호를 마스킹해야하며 sigfillset함수 호출이이를 달성합니다.

마지막으로, 신호 번호,struct sigaction의 주소, 이전 작업을 저장할 수있는 선택적 구조체의 세 가지 인수를 사용하는sigaction 호출로 신호 핸들러를 등록합니다.

이 경우 세 번째 인수를 무시하지만 nullptr을 매개 변수로 지정해야합니다. 문자열을 콘솔에 출력 한 다음 프로그램을 종료하여 핸들러의 올바른 실행을 쉽게 확인할 수 있도록cleanupRoutine 함수를 정의했습니다. 나머지 프로그램은 사용자가 SIGABRT신호를 보낼 때 중단되어야하는 무한 루프입니다. 프로그램을 테스트하려면 하나의 터미널 창에서 실행하고 다음 명령 kill -SIGABRT pid_num_of_program을 실행하여 두 번째 창에서 신호를 보냅니다.

#include <csignal>
#include <cstring>
#include <iostream>

void cleanupRoutine(int signal_number) {
  write(2, "printed from cleanupRoutine\n", 28);
  _exit(EXIT_SUCCESS);
}

int main() {
  struct sigaction sigabrt_action {};
  memset(&sigabrt_action, 0, sizeof(sigabrt_action));
  sigabrt_action.sa_handler = &cleanupRoutine;

  if (sigfillset(&sigabrt_action.sa_mask) != 0) {
    perror("sigfillset");
    exit(EXIT_FAILURE);
  }
  if (sigaction(SIGABRT, &sigabrt_action, nullptr) != 0) {
    perror("sigaction SIGABRT");
    exit(EXIT_FAILURE);
  }

  int i = 0;
  while (true) {
    i += 1;
  }

  exit(EXIT_SUCCESS);
}

신호 처리기에서sig_atomic_t 변수 사용

신호 처리기는 특정 기능을 갖는 데 필요한 특수한 유형의 함수입니다. 즉, 올바르게 작동 할 수있는 유일한 변수는 원자 변수입니다. 신호 처리기 실행 중에 설정할 수있는 정수인 특수 유형 sig_atomic_t가 있습니다. 이 변수는volatile 키워드로 선언되며 모든 수정 사항은 전역 적으로 표시됩니다. 다음 예제는 루프 문에이 변수를 조건으로 포함하는 방법을 보여줍니다.

핸들러는 변수를 1에서 0으로 만 설정하고 신호가 수신되면 프로그램을 종료하지 않습니다. 즉, 프로그램은 중단 된 지점부터 계속하려고합니다. 이 경우 루프 반복이 다시 시작되고 조건이 거짓으로 확인되면 루프에서 점프합니다. 이러한 방식으로 사용자는 신호를 사용하여 프로그램 동작을 제어 할 수 있습니다.

#include <csignal>
#include <cstring>
#include <iostream>

using std::cout;
using std::endl;

volatile sig_atomic_t shutdown_flag = 1;

void cleanupRoutine(int signal_number) { shutdown_flag = 0; }

int main() {
  struct sigaction sigabrt_action {};
  memset(&sigabrt_action, 0, sizeof(sigabrt_action));
  sigabrt_action.sa_handler = &cleanupRoutine;

  if (sigfillset(&sigabrt_action.sa_mask) != 0) {
    perror("sigfillset");
    exit(EXIT_FAILURE);
  }
  if (sigaction(SIGABRT, &sigabrt_action, nullptr) != 0) {
    perror("sigaction SIGABRT");
    exit(EXIT_FAILURE);
  }

  int i = 0;
  while (shutdown_flag) {
    i += 1;
  }
  cout << "Exiting ..." << endl;

  exit(EXIT_SUCCESS);
}
작가: Jinku Hu
Jinku Hu avatar Jinku Hu avatar

Founder of DelftStack.com. Jinku has worked in the robotics and automotive industries for over 8 years. He sharpened his coding skills when he needed to do the automatic testing, data collection from remote servers and report creation from the endurance test. He is from an electrical/electronics engineering background but has expanded his interest to embedded electronics, embedded programming and front-/back-end programming.

LinkedIn Facebook