2015-12-24 6 views
5

apt-cache search <some query>のように長時間実行するsystemコマンドを使用している場合は、^C経由で親のPerlプロセスに送信するSIGINTをそのような方法で転送する方法がありますすべての子プロセスが収穫されるということです。Perl forward SIGINTを `system`コマンドから親プロセスに転送する

この例には、適切な動作がありません。シグナルは子プロセスに送られます。

#!/usr/bin/env perl 
use strict; 
use warnings FATAL => 'all'; 
use autodie; 

# long running command on ubuntu, produces a ton of output. 
# replace with your favorite long running command 
system("apt-cache search hi"); 

print("Perl did not catch SIGINT even with autodie\n"); 

私はsystem("apt-cache search hi &")によって作成される子のPIDを獲得する方法を周りに検索しようとしたが、いずれかを見つけることができませんでしたので、私は、プロセスをINGのシグナルハンドラを書くfork INGとexecを試してみました。 apt-cache自体がcloneシステムコール経由でいくつかのプロセスを起動するため、これは機能しません。ハンドローリング私は私が欲しい、本質的に何を推測するプロセスツリーの一部を歩くと

#!/usr/bin/env perl 
use strict; 
use warnings FATAL => 'all'; 
use autodie; 

my $cpid; 

$SIG{INT} = sub { 
    kill 'KILL', $cpid; 
    exit; 
}; 

# long running command on ubuntu, produces a ton of output. 
# replace with your favorite long running command 
$cpid = fork; 
if ($cpid == 0) { 
    exec 'apt-cache', 'search', 'hi'; 
} 

print "Perl did not catch SIGINT even with autodie\n"; 

をクリーンアップするためにいくつかのロジックがsystemが立ち上げた子プロセスが原因そうSIGINTなどの信号に出るかどうかを決定する方法のどちらかであります私は、Perlスクリプト自体を後にするか、子プロセスを歩いてプロセス管理の奇妙なケースがきれいに移植可能に処理されるようにすることができます。

+0

'IPC :: Run'はシステムではなく、あなたが必要とするものです。あるいは、 'SIGCHLD'を" IGNORE "に設定すると、自動的に終了時に刈り取られます。 – Sobrique

+0

コマンドがユーザーによってアボートされたかどうかを検出する方法は次のとおりです。[Signal number 2の名前](http://stackoverflow.com/questions/29862178/name-of-signal-number-2) –

+0

も参照[独自のプロセスグループでプロセスを開始する方法は?](http://stackoverflow.com/questions/5809034/in-linux-how-to-start-a-process-in-its-own-process-group-そして - それ以上) –

答えて

6

子プロセスグループの先頭にしてから、プロセスグループ全体に信号を送信します。

#!/usr/bin/perl 

use strict; 
use warnings; 
use autodie; 

use POSIX qw(setpgid); 

my $child_pid; 

$SIG{INT} = sub { 
    kill INT => -$child_pid if $child_pid; 
    exit(0x80 | 2); # 2 = SIGINT 
}; 

my $child_pid = fork(); 
if (!$child_pid) { 
    setpgid($$); 
    exec 'apt-cache', 'search', 'hi'; 
} 

WAIT: { 
    no autodie; 
    waitpid($child_pid, 0); 
    redo WAIT if $? == -1 and $!{EINTR}; 
    die $! if $? == -1; 
} 

exit(($? >> 8) | (0x80 | ($? & 0x7F))); 
+0

'$ INT_> - $ child_pid;が$ child_pidなら' kill INT =>これはWindows固有ですか? –

+1

いいえ、かなり反対です。 WindowsはPOSIXシグナルやプロセスグループを持っていません(WindowsではCtrl-CやCtrl-Breakのような非常に少数のシグナルをコンソールアプリケーションに送るのに 'kill'を使うことができます)。 – ikegami

+0

それでは、cpidを否定するのは何ですか? –

関連する問題