2016-04-30 50 views
7

Mam następujący problem, który zrekonstruowałem w tych dwóch mini skryptach perla. Jest to główny scenariusz:Wysyłanie sygnału do skryptu Perl podczas zamykania uchwytu pliku

#!/usr/bin/perl 
$SIG{INT} = \&signal_handler_one; 
open(my $pipe, "|-", "/home/pa/Desktop/POC2"); 
close $pipe; 
sub signal_handler_one{ 
    print "This is expected to print\n"; 
} 

Na trzeciej linii otwiera rurę do tego skryptu:

#!/usr/bin/perl 
$SIG{INT} = \&signal_handler_two; 
sleep(10); 
sub signal_handler_two{ 
    print "This isn't expected to print\n"; 
} 

Problem polega na tym, że gdy zacznę pierwszy scenariusz, a następnie wysłać SIGINT do niego podczas to zamyka rurę na linii 4, signal_handler_two jest odpalane zamiast signal_handler_one. Dlaczego tak się zachowuje? Czy jest jakiś sposób obejścia tego (moim celem jest uzyskanie signal_handler_one do wykonania).

Edit: pierwotnie wysłany sygnał na terminalu używając Ctrl + C, co powoduje „Nie należy oczekiwać, aby wydrukować” do wydrukowania. Ale kiedy wysyłam sygnał za pomocą kill do procesu nadrzędnego z innego terminala, po prostu go ignoruje.

Edycja 2: ostatecznie rozwiązać go nie używając otwarty dostać się do rury, ale przez ręczne rozwidlone, execing a następnie czeka na dziecko zamiast po prostu wywołanie blisko . Teraz wszystko działa dobrze. Wygląda na to, że to zachowanie było specyficzne dla mojego środowiska, ale jeśli ktoś mógł odtworzyć ten sam błąd, proszę dać mi znać.

+1

Więc drugi skrypt to "POC2"? Jak dokładnie wysłać sygnał? Skąd wiesz, że to jest, gdy pierwszy skrypt zamyka rurę? – Borodin

+0

Wysyłam go przez Ctrl + C na terminalu. Zamknij bloki wywołania, dopóki drugi proces nie zostanie zakończony, więc mam 10-sekundowe okno do wysłania Ctrl + C we właściwym czasie. Tak, POC2 to drugi skrypt. – Void

+1

Myślę, że przekonasz się, że Ctrl-C wysyła sygnał do ostatnio aktywnego procesu. Możesz być bardziej selektywny, pobierając pierwszy proces, aby zgłosić swój PID za pomocą 'print" $$ \ n "', a następnie 'kill -s INT 1234' w linii poleceń, zastępując' 1234' aktualnym PID – Borodin

Odpowiedz

3

Nie mogę odtworzyć zachowania, które obserwujesz. Po naciśnięciu CTRL-C w terminalu, zarówno dziecko i rodzic otrzymuje natychmiast SIGINT:

use diagnostics; 
use feature qw(say); 
use strict; 
use warnings; 

$SIG{INT} = sub { say "This is expected to print"; die }; 
my $pid = open (my $pipe, "|-", "script.pl"); 
say "PID = $pid"; 
eval { 
    say "Closing.."; 
    my $close_ok = close $pipe; # Note "close" here waits for child to exit 
    if (! $close_ok) { 
     say "Error closing: $!"; 
    } 
    else { 
     say "Close done."; 
    } 
}; 
if ([email protected]) { 
    say "Parent caught SIGINT."; 
} 

gdzie script.pl jest:

#! /usr/bin/env perl 

use feature qw(say); 
use strict; 
use warnings; 

$SIG{INT} = sub { die }; 
eval { 
    say "Sleeping.."; 
    for (1..5) { 
     sleep 1; 
     say $_; 
    } 
}; 
if ([email protected]) { 
    say "Child caught SIGINT."; 
    exit; 
} 

wyjście uruchomiony pierwszy program w terminalu (gnome-terminal na Ubuntu 16,04) wynosi:

PID = 1746 
Closing.. 
Sleeping.. 
1 
2 
^CThis is expected to print 
Child caught SIGINT. 
Parent caught SIGINT. 
Uncaught exception from user code: 
    refcnt: fd -1 < 0 

Należy zauważyć, że nie jest przechwycony wyjątkiem refcnt: fd -1 < 0. Nie mam pojęcia, co to jest. Może dlatego, że close nie udało się?

+0

Sądzę, że coś jest nie tak z moim środowiskiem. Jeśli wykonam twój kod, nie wydrukuje "Parent caught SIGINT.". – Void

+0

@Void, nie, twoje środowisko jest poprawne. Nie widzisz linii "Parent", ponieważ wysyłasz swój SIGINT podczas 'close' [który ignoruje SIGINT] (http://stackoverflow.com/a/4719492/132382). Ta odpowiedź robi coś innego - wysłanie SIGINT zbyt wcześnie lub za późno, np. – pilcrow

+0

@pilcrow Byłem pewien, że wysłałem sygnał podczas 'close'. Możesz zobaczyć na wyjściu komunikat "Closing..", a następnie czeka na zakończenie programu. To musi się zdarzyć wewnątrz 'close', ponieważ instrukcja print po' close' nie jest wyświetlana. Po 5 sekundach 'close' wróci, jeśli nie uderzę w' CTRL-C' .. Tak interpretuję wyjście . Jestem ciekawy, dlaczego masz na myśli, że nie wysyła 'SIGINT' podczas' close'? –