2013-04-02 11 views
13

Dlaczego przerywanie procesu ruby ​​z dzieckiem utworzonym za pomocą połączenia z numerem system nie przerywa samego procesu ruby? Powinny należeć do tej samej grupy, więc należy je przerwać. Również nie jest to poprawne dla ruby2.0.Dziecko przerywane wywołane z ruby ​​

Biorąc Ruby 1.8.7 łata 371, Ruby 1.9.3 łata 392 i ruby2.0 łata 0:

Running ruby1.8 -e 'system "sleep 100"; p $?; sleep' w bash i naciskając ^C zabija tylko wewnętrzne wezwanie do sleep 100.

Ruby 1.9 zachowuje się identycznie.

Choć działa ruby2.0 -e 'system "sleep 100"; p $?; sleep' przerwań zarówno wewnętrzny proces dowodzenia i rubin itself.2.0.0-P0

--EDIT--

Czytając źródła Odkryłam, że obsługa SIGINT, SIGQUIT i SIGHUP jest przełączono na zignorowanie w metodzie rb_syswait, która czeka, aż utworzony proces podrzędny zakończy działanie, a następnie przywróci procedury obsługi (rb_syswait w ruby v1.8.7-p370, ruby v1.9.3-p362 i bez blokowania procedur obsługi w ruby v2.0.0-p0).

Dlaczego to się robi i dlaczego tylko dla system i IO.popen, nie %x{} lub fork{}?

+0

Czy chcesz poznać szczegóły implementacji lub jak obejść ten problem? –

+0

@ SemyonPerepelitsa: zarówno + co powinno być uważane za normalne zachowanie – tig

+0

@ SiemioPerepelitsa teraz tylko dlaczego jest zrobione i najlepsze obejścia – tig

Odpowiedz

1

Aby obejść ten problem, można samodzielnie propagować SIGINT. Można sprawdzić, czy polecenie System wyszedł ze względu na sygnał, a jeśli tak podnieść SIGINT:

ruby1.8 -e 'system "sleep 100"; p $?; Process.kill("INT",0) if $?.signaled?; sleep' 
+0

Nie pomaga, jeśli proces obsługuje przerwań: 'ruby1.8 -e 'system% q {ruby1.8 - e "Signal.trap (% q {INT}) {exit}; sleep 10"}; p $ ?; Process.kill ("INT", 0) jeśli $? Sygnalizowane ?; sleep'' – tig

+0

@tig To prawda. W takim przypadku potrzebowałbyś innego sposobu (być może specjalnego kodu wyjścia w potomku), aby wskazać, że sygnał został odebrany przez proces potomny. –

+0

Nie pomoże, jeśli nie będę w stanie kontrolować kodu wyjścia dziecka – tig

-1

To nie wydaje się być kwestia Ruby ale system operacyjny, którego nie określił. Grupowanie procesów i niskopoziomowe routing systemowy wykonywane są przez jądro systemu operacyjnego.

+0

Różnica jest w rubinach, porównaj kod źródłowy pod podanymi linkami – tig

+0

Uruchom oba polecenia w "strace" i porównaj wyjścia. Być może "setpgid" jest wywoływane w jednym przypadku, a nie drugim? – dig

Powiązane problemy