2016-04-30 84 views
7

我有以下問題,我已在這兩個迷你Perl腳本中重新構建。 這是主要的腳本:在關閉文件句柄時向Perl腳本發送信號

#!/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"; 
} 

在第三行它會打開一個管道,這個腳本:

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

的問題是,當我開始了第一個腳本,然後發送SIGINT給它,而它正在關閉第4行的管道,signal_handler_two被觸發而不是signal_handler_one。爲什麼它的行爲如此?有沒有辦法解決這個問題(我的目標是讓signal_handler_one執行)。

編輯: 我最初使用Ctrl + C在終端上發送信號,導致打印出「This is not expected to print」。但是當我使用kill從另一個終端向父進程發送信號時,它只是忽略它。

編輯2: 我終於解決它不使用開放拿到管,而是由人工分叉execing然後等待孩子而不是僅僅調用接近 。現在一切似乎都很好。看起來這種行爲是特定於我的環境的,但如果任何人都能重現同樣的錯誤,請告訴我。

+1

所以第二個腳本是'POC2'?你如何發送信號?你怎麼知道它是在第一個腳本關閉管道的時候? – Borodin

+0

我通過終端上的Ctrl + C發送它。關閉呼叫阻塞,直到第二個過程終止,因此我有10秒的時間窗口讓我在正確的時間發送Ctrl + C。是的,POC2是第二個劇本。 – Void

+1

我想你會發現Ctrl-C將信號發送到最近激活的進程。你可以更具選擇性地讓第一個程序用'print'$$ \ n「'來報告PID,然後在命令行上用'kill -s INT 1234'報告,用實際的PID替換'1234' – Borodin

回答

3

我無法重現您正在觀察的行爲。當我在終端按CTRL-C,兩個子和父立即接收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."; 
} 

其中script.pl是:

#! /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; 
} 

在Ubuntu在終端運行第一程序(gnome-terminal的輸出16.04)是:

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 

請注意,有一個未捕獲的異常refcnt: fd -1 < 0。我不知道那是什麼。也許是因爲close沒有成功?

+0

我想那時我的環境有問題。如果我執行你的代碼,它不會打印「Parent caught SIGINT。」。 – Void

+0

@Void,不,你的環境是正確的。您看不到「Parent」行,因爲您在'close' [忽略SIGINT]期間發送了SIGINT(http://stackoverflow.com/a/4719492/132382)。這個答案做了一些不同的事情 - 發送SIGINT太早或太遲,例如, – pilcrow

+0

@pilcrow我確信我在'關閉'期間發送信號。你可以在輸出中看到它說'Closing..',然後等待程序退出。這必須發生在'close'內部,因爲'close'後面的print語句沒有顯示。5秒後,如果我沒有按'CTRL-C','close'將會返回。這就是我如何解釋輸出。我很好奇爲什麼你的意思是它在'close'期間不發送'SIGINT'? –