2017-01-13 20 views
2

나는이 기간에 따라 스크립트 ::에서는 ReadLine 및 LWP :: 해당 UserAgentCTRL + C와 현재의 LWP 요청을 죽여

논리는,이처럼 그것이 LWP 할 것 run에서

while (defined ($_ = $term->readline('console> '))) 
{ 
    next unless $_; chomp; 

    if ($_ eq 'exit') 
    { 
     last; 
    } 
    &run ($_); 
} 

sub run { 
    my $ua = LWP::UserAgent->new; 
    my $resp = $ua->get (...); 

    say $resp->content; 
} 

의뢰. 지금은 단지 LWP는 종료하지 CTRL + C을 누르면, 전체 펄 스크립트도 종료됩니다.

나는 단지 LWP 요청을 죽이고 싶어. 어떤 아이디어?

나는 SIGINT 핸들러를 추가 할 수 있습니다,하지만 난 핸들러 코드를 중지

+0

하는'실행이()' "_will LWP을합니까 어떻게 의뢰_"? 새 프로세스를 생성하거나 LWP를 실행하고 하위가 반환 될 때까지 대기합니까? – zdim

+0

@zdim 두 번째 것 – daisy

+0

'run'을위한 코드를 보여주세요. 그렇지 않으면 우리는 추측 할 것을 강요 당하고 잘못 받아 들일 것입니다. – Borodin

답변

2

신호를 예외로 변환합니다.

local $SIG{INT} = sub { die "SIGINT\n" }; 

일반적으로, 하나는 다음 eval BLOCK의 코드를 포장 것이지만, LWP :: 해당 UserAgent는 이러한 예외를 잡는다 오류 응답을 반환합니다. 예를 들어

,

use LWP::UserAgent; 
my $ua = LWP::UserAgent->new(); 
my $response = do { 
    local $SIG{INT} = sub { die "SIGINT\n" }; 
    $ua->get("http://localhost/zzz.crx") 
}; 
say $response->is_success ? "Successful" : "Unsuccessful"; 
say $response->code; 
say $response->status_line; 

출력에는 SIGINT가 수신되지 않을 경우 : SIGINT받은 경우

Successful 
200 
200 OK 

출력 :

Unsuccessful 
500 
500 SIGINT 
1

한 가지 방법을 무엇을해야하는지 모른다는 자식 프로세스에서 실행하고 kill 부모의 시그널 핸들러에서 아이 SIGINT하는 것입니다 부모가 수신합니다. 부모는 신호가 처리 된 이후에도 운전을 계속합니다.

use warnings; 
use strict; 
use feature 'say'; 

$SIG{INT} = \&sigint_handler; # or: $SIG{INT} = sub { ... }; 

say "Parent $$ start."; 

my $pid = run_proc(); 
my $gone_pid = waitpid $pid, 0; # check status, in $? 

say "Parent exiting"; 

sub run_proc 
{ 
    my $pid = fork // die "Can't fork: $!"; 
    if ($pid == 0) {        # child process 
     say "\tKid, sleep 5 (time for Ctrl-C)"; # run your job here 
     sleep 5;         
     say "\tKid exiting."; 
     exit; 
    } 
    return $pid; 
} 

sub sigint_handler { 
    if ($pid and kill 0, $pid) { 
     say "Got $_[0], send 'kill TERM' to child process $pid."; 
     my $no_signalled = kill 15, $pid; 
    } 
    else { die "Got $_[0]" } # or use exit 
} 

진단 인쇄용 코드가 많이 있습니다. 일부 의견은 kill는 신호를 보냅니다

따릅니다. 어떤 방법으로도 프로세스가 종료되지는 않습니다. 이것을 kill $pid, 0으로 확인하십시오. 프로세스가 을 수확하지 않은 경우 참을 반환합니다. (좀비 인 경우에도). 내 시스템에서 TERM15이고 매우 일반적인 경우에도 확인하십시오. 아이가 실행되지 않을 때

신호는 한 번에 올 수 있습니다. 처리기는 먼저 $pid이 있는지 여부를 확인하고 그렇지 않은 경우 SIGINT을 존중합니다. 적절하게 변경하십시오.

fork 뒤에 부모는 if ($pid == 0)을 초과하고 바로 $pid을 반환합니다.

을 어린이에 설치할 수 있습니다. 어린이가 주문할 수없는 경우 정리할 수 있습니다.

SIGINT 핸들러뿐만 아니라 아이의 부족하게됩니다

, 그래서 "Got $_[0] ..." 두 번 인쇄됩니다. 이것이 문제라면 신호를 무시하도록 자식에게 핸들을 추가하십시오 ($SIG{INT} = 'IGNORE';). 아이가 실행되는 동안 Ctrl-C를 칠 장소와이로는 $?를 통해 확인할 수 있습니다 종료되면 출력은 systemin perlvar를 참조 아이의 상태

 
Parent 9334 start. 
     Kid, sleep 5 (time for Ctrl-C) 
^CGot INT, send 'kill TERM' to child process 9335. 
Parent exiting 

입니다.

문서 : fork (그리고 exec, system), %SIG in perlvar, waitpid, perlipc, kill의 일부.

부모와 통신하는 데 필요한 아동에 수행 된 작업이 다음 할 것이 더있을 것입니다 경우

. 그러나 질문에 추가 된 코드 스 니펫은 그렇지 않다는 것을 나타냅니다.

0

$ua->request으로 전화하면 콜백을 제공해야합니다. 해당 콜백에 die을 발급하면 전송이 종료됩니다.

그런 다음 Ctrl-C 신호 처리기에 플래그 변수를 설정하면 콜백에 die 플래그를 설정하면됩니다.

PC로 돌아갈 때, 그리고 run 서브 루틴이 무엇을 표시했는지 알 수 있도록 몇 가지 코드를 작성합니다. 여기


바로 보이는 몇 가지 코드입니다,하지만 난 run 어떤 서브 루틴에 대한 무서운 식별자하는 네트워크 전송을 시작하고 결과를 출력 특히 하나를 조심 존재

에 그것을 테스트 할 수 없습니다 :read_size_hint를 줄이는 것이 콜백을 일으킬 것

sub run { 

    my ($url) = @_; 

    my $die; 
    local $SIG{INT} = sub { $die = 1 }; 

    my $ua = LWP::UserAgent->new; 

    my $resp = $ua->get(
     $url, 
     ':content_cb' => sub { 
      die "Interrupted LWP transfer" if $die; 
      my ($data, $resp, $proto) = @_; 
      print $data; 
     }, 
     ':read_size_hint' => 1024 
    ); 

    print "\n"; # Emulate additional newline from `say` 
} 

참고 데이터의 작은 덩어리를 더 자주 호출 할 수 있습니다. 그러면 Ctrl-C에 대한 응답이 향상되지만 전송 효율은 저하됩니다.