Signal

Signal

Signal 모듈은 운영체제가 제공하는 시그널(signal) 시스템에 접근할 수 있게 해 주는 모듈이에요.

출처: Ruby 3.3 API

본문

많은 운영체제에서 실행 중인 프로세스에 시그널을 보낼 수 있어요. 어떤 시그널은 프로세스에 정해진 효과를 주고, 어떤 시그널은 코드 수준에서 잡아서(trap) 원하는 동작을 하게 만들 수 있어요. 예를 들어 USR1 시그널을 잡아 디버깅을 켜고 끄는 용도로, TERM을 써서 통제된 종료를 시작하는 용도로 쓸 수 있지요.

pid = fork do
  Signal.trap("USR1") do
    $debug = !$debug
    puts "Debug now: #$debug"
  end
  Signal.trap("TERM") do
    puts "Terminating..."
    shutdown()
  end
  # . . . do some work . . .
end

Process.detach(pid)

# Controlling program:
Process.kill("USR1", pid)
# ...
Process.kill("USR1", pid)
# ...
Process.kill("TERM", pid)

실행 결과는 이렇게 돼요.

Debug now: true
Debug now: false
Terminating...

사용 가능한 시그널 이름 목록과 그 해석은 시스템에 따라 달라요. 시그널 전달 의미론(semantics)도 시스템마다 다를 수 있고, 특히 시그널 전달이 항상 신뢰할 수 있는 건 아니라는 점을 기억해 두면 좋아요.

Public Class Methods

list → a_hash

시그널 이름을 해당 시그널 번호에 매핑한 해시를 돌려줘요.

Signal.list   #=> {"EXIT"=>0, "HUP"=>1, "INT"=>2, "QUIT"=>3, "ILL"=>4, "TRAP"=>5, "IOT"=>6, "ABRT"=>6, "FPE"=>8, "KILL"=>9, "BUS"=>7, "SEGV"=>11, "SYS"=>31, "PIPE"=>13, "ALRM"=>14, "TERM"=>15, "URG"=>23, "STOP"=>19, "TSTP"=>20, "CONT"=>18, "CHLD"=>17, "CLD"=>17, "TTIN"=>21, "TTOU"=>22, "IO"=>29, "XCPU"=>24, "XFSZ"=>25, "VTALRM"=>26, "PROF"=>27, "WINCH"=>28, "USR1"=>10, "USR2"=>12, "PWR"=>30, "POLL"=>29}
signame(signo)  →  string or nil

시그널 번호를 시그널 이름으로 변환해요. signo가 유효하지 않은 시그널 번호면 nil을 돌려줘요.

Signal.trap("INT") { |signo| puts Signal.signame(signo) }
Process.kill("INT", 0)

실행 결과는 INT예요.

trap( signal, command ) → obj
trap( signal ) {| | block } → obj

시그널 처리 방식을 지정해요. 첫 번째 인자는 시그널 이름("SIGALRM", "SIGUSR1" 등)이나 시그널 번호예요. 시그널 이름에서 "SIG"는 생략할 수 있어요. command 또는 블록이 시그널 발생 시 실행할 코드를 지정해요.

  • command"IGNORE""SIG_IGN"이면 시그널을 무시해요.
  • "DEFAULT""SIG_DFL"이면 Ruby의 기본 핸들러를 호출해요.
  • "EXIT"면 시그널로 스크립트를 종료해요.
  • "SYSTEM_DEFAULT"면 운영체제의 기본 핸들러를 호출해요.
  • 그 외에는 주어진 command나 블록을 실행해요.

특수 시그널 이름 "EXIT" 또는 시그널 번호 0은 프로그램 종료 직전에 호출돼요. trap은 주어진 시그널에 대한 이전 핸들러를 돌려줘요.

Signal.trap(0, proc { puts "Terminating: #{$$}" })
Signal.trap("CLD")  { puts "Child died" }
fork && Process.wait

실행 결과는 다음과 같아요.

Terminating: 27461
Child died
Terminating: 27460