1. 언제 쓰는가?
- 아래 시그널들이 발생했을 때, 실시할 로직을 만들기 위함!
- 대표적으로는
- 사용자가
ctrl+c 로 프로그램을 종료
하여 발생하는 시그널
현재 터미널 세션과 연관된 포어그라운드 프로세스 그룹에 있는 프로세스가 종료
되는 경우 발생하는 시그널
2. 예시
import signal
def graceful_exit(realsense_components: List[base.Base],
total_shm_info: shared_memory.TotalShmInfo):
"""graceful_exit routine to stop all components and release resources."""
for component in realsense_components:
try:
component.graceful_exit()
except Exception as e:
print(f"Error stopping {component}: {e}")
total_shm_info.graceful_exit()
if __name__ == '__main__':
def signal_handler(sig: int, frame: Optional[FrameType]) -> None:
print("시그널 받음, 우아하게 종료 중...")
graceful_exit(realsense_components, total_shm_info)
exit(0)
signal.signal(signal.SIGINT, signal_handler)
signal.signal(signal.SIGTERM, signal_handler)
3. 특징
- 멀티스레드 환경에서는 주 스레드만 신호를 받을 수 있습니다.
- 운영 체제는 신호를 프로세스 단위로 전달
- 이는 신호가 특정 스레드에게 직접 전달되는 것이 아니라, 프로세스를 대표하는 주 스레드에게 전달된다는 의미
- 여기서 "주 스레드"란 프로세스가 시작될 때 생성되는 초기 스레드를 의미
- 아래는 여러 signal 종류를 나타냅니다. 주로 UNIX 및 UNIX 계열 시스템(Linux, macOS 등)에서 사용됩니다. Windows에서는 제한적인 신호만 사용할 수 있습니다.
- 참고 (포어그라운드 vs 백그라운드 프로세스)
4. signal이 전달되는 범위
SIGINT
와 같은 신호의 전달 방식은 아래 요소에 따라 달라집니다.
- 운영 체제
- 프로세스의 구성,
- 프로세스가 실행되는 방식
4.1. 신호의 전달
- 신호는 보통
현재 터미널 세션과 연관된 포어그라운드 프로세스 그룹
에 전송
- 그룹 내의 모든 프로세스는 이 신호를 받게 되며, 기본적으로는 이 신호를 받았을 때 종료
4.2. 포어그라운드 vs. 백그라운드 프로세스
- 포어그라운드 프로세스:
- 사용자 입력과 직접 상호작용하는 프로세스로, 터미널 세션에 바인딩
SIGINT
와 같은 신호는, 주로 이러한 포어그라운드 프로세스에 영향을 줌
- 백그라운드 프로세스:
- 사용자와 직접 상호작용하지 않고 백그라운드에서 실행되는 프로세스
- 일반적으로
SIGINT
신호는 백그라운드 프로세스에 전송되지 않음
4.3. 프로세스 그룹과 신호
- 운영 체제:
프로세스를 그룹으로 관리
- 터미널 또는 쉘:
포어그라운드 프로세스 그룹을 관리
SIGINT
같은 신호가 발생하면, 해당 터미널 세션의 포어그라운드 프로세스 그룹에 속한 모든 프로세스에 신호가 전송
- 이는 단일 프로세스에만 신호를 보내는 것이 아니라, 연관된 프로세스 그룹에 신호를 전송한다는 것을 의미
시그널 신호 무시하는 방법
signal.signal(signal.SIGINT, signal.SIG_IGN)
signal.signal(signal.SIGTERM, signal.SIG_IGN)