2015-11-04 8 views
1

Я пишу обертку для набора дочерних процессов, которые я хочу отреагировать на некоторые сигналы и передать их детям. Так, например, если обертка получает QUIT, она должна отправить QUIT всем детям (не только прямым детям, но и всем процессам, порожденным).Игнорировать сигнал, отправленный моей собственной группе процессов

Так что я использую setsid, а затем захватываю сигналы, с которыми я хочу обращаться, с кодом, который просто выдает kill(sig, 0). Когда я это делаю, обертка снова получает сигнал (являясь лидером сеанса и внутри группы процессов), и наступает бесконечный цикл.

Я подумывал установить какой-то флаг (already_handled_sig_X) и посоветоваться с ним перед тем, как позвонить kill, но (а) он выглядит неуклюжим и (б) когда я удаляю флаг?

КСТАТИ: язык реализации является рубин, так что если вы хотите поставить примеры и хочется писать их в Ruby, я ценю это, в противном случае - не беспокойтесь, я могу справиться с C.

Вот мой (наивная) реализация:

def run_stuff(cmd) 
    fork do 
    Process.setsid 
    trap(:QUIT) { Process.kill(:QUIT, 0) } 
    trap(:TERM) { Process.kill(:TERM, 0) } 
    IO.popen(cmd) do |io| 
     while line = io.gets 
     $log.warn line 
     end 
    end 
    end 
end 

ответ

1

В конце концов, я просто установил флаг, чтобы игнорировать дополнительные сигналы. Приведенный выше код образца должен быть изменен таким образом:

def run_stuff(cmd) 
    fork do 
    Process.setsid 
    shuttingdown = false 
    trap(:QUIT) do 
     next if shuttingdown 
     shuttingdown = true 
     Process.kill(:QUIT, 0) 
    end 
    trap(:TERM) do 
     next if shuttingdown 
     shuttingdown = true 
     Process.kill(:TERM, 0) 
    end 
    IO.popen(cmd) do |io| 
     while line = io.gets 
     $log.warn line 
     end 
    end 
    end 
end 
Смежные вопросы