2010-03-21 17 views
5

मैं एक आईआरसी बॉट (Bot::BasicBot) चला रहा हूं जिसमें दो बाल प्रक्रियाएं File::Tail चल रही हैं, लेकिन बाहर निकलने पर, वे समाप्त नहीं होते हैं। इसलिए मैं उन्हें बाहर निकलने से पहले Proc::ProcessTable इस तरह का उपयोग कर killling हूँ:बाहर निकलने से पहले पर्ल में बाल प्रक्रियाओं को मारने का सही तरीका क्या है?

my $parent=$$; 
my $proc_table=Proc::ProcessTable->new(); 
for my $proc (@{$proc_table->table()}) { 
    kill(15, $proc->pid) if ($proc->ppid == $parent); 
} 

यह काम करता है, लेकिन मैं इस चेतावनी मिलती है:

 
14045: !!! Child process PID:14047 reaped: 
14045: !!! Child process PID:14048 reaped: 
14045: !!! Your program may not be using sig_child() to reap processes. 
14045: !!! In extreme cases, your program can force a system reboot 
14045: !!! if this resource leakage is not corrected. 

और क्या मैं कर सकता हूँ बच्चे प्रक्रियाओं को बंद करने? फोर्कड प्रक्रिया forkit विधि Bot::BasicBot में विधि का उपयोग करके बनाई गई है।

नमूना स्क्रिप्ट:

package main; 

my $bot = SOMEBOT->new (server => 'irc.dal.net', channels => ['#anemptychannel']); 

$SIG{'INT'} = 'Handler'; 
$SIG{'TERM'} = 'Handler'; 

sub Handler { 
$bot->_stop('Leaving.'); 
} 

$bot->run; 

package SOMEBOT; 

use base qw(Bot::BasicBot); 
use File::Tail; 
use Proc::ProcessTable; 
sub irc_error_state { die if $_[10] =~ /Leaving\./; } 
sub help { return; } 


sub stop_state { 
my $parent=$$; 
my $proc_table=Proc::ProcessTable->new(); 
for my $proc (@{$proc_table->table()}) { 
    kill(15, $proc->pid) if ($proc->ppid == $parent); 
} 
die; 

} 

sub connected { 
my $self = shift; 

$self->forkit (
       run  => \&announcer, 
       body => '/home/somebody/somefile.txt', 
       channel => '#anemptychannel', 
      ) unless $self->{log1}; 
$self->{log1} = 1; 


$self->forkit (
       run  => \&announcer, 
       body => '/home/somebody/anotherfile.txt', 
       channel => '#anemptychannel', 
      ) unless $self->{log2}; 
$self->{log2} = 1; 

} 

sub announcer { 
my $announcefile = shift; 
my $file=File::Tail->new(name => $announcefile, maxinterval=>5, adjustafter=>7); 
while (defined(my $line=$file->read)) { chomp $line; print "$line\n"; } 
} 
+2

हाय, आप बच्चे की प्रक्रियाओं को कैसे मार रहे हैं इसके साथ कोई समस्या नहीं है। चेतावनी सिर्फ यह कह रही है कि जब आप इन प्रक्रियाओं को मरते हैं तो आपने पीओई कॉलबैक पंजीकृत नहीं किया है - आपको उन्हें POE-> कर्नेल-> sig_child() के साथ पंजीकृत करने की आवश्यकता है। देखें: http://kobesearch.cpan.org/htdocs/POE/POE/Kernel.html#sig_child_PROCESS_ID_EVENT_NAME – Martin

उत्तर

0

मैं क्यों अपने बच्चे की प्रक्रिया ठीक से समाप्त नहीं कर रहे हैं ध्यान देना चाहते हैं। "सामान्य" परिस्थितियों में, माता-पिता को कुछ भी करने की ज़रूरत नहीं है (शायद waitpid पर कॉल करें यदि आप परिणामों की परवाह करते हैं, या जब तक वे पूरा नहीं कर लेते हैं)।

यह वास्तव में अभी तक कोई जवाब नहीं है - आपको शायद बच्चों में कुछ कोड पेस्ट करना होगा। लेकिन थोड़ी सी सलाह - सरल प्रोग्रामों से शुरू करें जो आपके लिए ऐसा करने के लिए एक सीपीएएन मॉड्यूल पर भरोसा करने के बजाय मैन्युअल रूप से fork पर कॉल करें। यह समझना महत्वपूर्ण है कि सिस्टम द्वारा कई प्रक्रियाओं को कैसे नियंत्रित किया जाता है। फिर जब आपको यह मिल जाए, तो आप अपने लिए कई प्रक्रियाओं को संभालने के लिए कुछ ढांचे का लाभ उठा सकते हैं।

यदि आपने हाल ही में ऐसा नहीं किया है, तो आप शायद perldoc perlfork के माध्यम से भी पढ़ना चाहिए, और कुछ उदाहरणों को आजमाएं।

+0

शायद क्योंकि मैं बॉट को ठीक से समाप्त नहीं कर रहा हूं। मैंने कुछ दिनों पहले एक सवाल पूछा था। http://stackoverflow.com/questions/2471373/how-do-i-correctly-shutdown-a-botbasicbot-bot-based-on-poecomponentirc – rarbox

1

मैं मॉड्यूल आप का उल्लेख से किसी के साथ परिचित नहीं हूँ, लेकिन जब मैं है कि अतीत में पर्ल कार्यक्रमों forking लिखा है, यह आमतौर पर मुख्य माता पिता की प्रक्रिया में इस लाइन डालने के लिए पर्याप्त है:

$SIG{CHLD} = sub { wait }; 

इस तरह, जब कोई बच्चा प्रक्रिया निकलता है और माता-पिता की प्रक्रिया एक सिग्चल सिग्नल प्राप्त करती है, तो यह स्वचालित रूप से wait के साथ बच्चे को वापस ले जाती है।

+0

की कोशिश की है कि, और यह काम नहीं किया। मैंने पहली बार Ctrl + C मारा और यह कुछ भी नहीं किया। मैंने इसे फिर से किया और इसे बाल प्रक्रियाओं को मारने के बिना समाप्त कर दिया गया। बच्चे की प्रक्रिया अनिश्चित काल तक चलनी चाहिए (जैसे "पूंछ-एफ" चलाने की तरह) जब तक कि मारे गए न हों। यह अपने आप खत्म नहीं होगा। – rarbox

1

संस्करण 0.82 के रूप में, Bot::BasicBot बाहर निकलने पर उत्कृष्ट बाल प्रक्रियाओं (forkit() द्वारा निर्मित) को मार देगा।

1

मैं एक पुराने पोस्ट को खोदकर निकाल रही है, लेकिन मैं इस सवाल का और एक गूगल खोज शीर्ष परिणाम के रूप में इस डाल करने के लिए एक जवाब के लिए देख रहा था। तो, अगर किसी और पर इस पर ठोकर खाई, तो मैंने यह कैसे किया।

forking से पहले, एक pipe की स्थापना की तो अपने काँटेदार प्रक्रियाओं संवाद कर सकते हैं:

pipe PARENTRECEIVE,CHILDSEND;

कांटा अपनी प्रक्रिया और बच्चे माता-पिता अपनी नई प्रक्रिया ID immendiately भेज दिया है। फिर जब आपको लगता है बच्चे तो त्रिशंकु है (या तो एक टाइमर या एक SIG के माध्यम से) आप बच्चे प्रक्रिया को मार सकता है:

my $pid = fork(); 
if ($pid eq 0) { 
    #child block 
    my $cid = $$;  
    print CHILDSEND "$cid\n"; 
    <do child stuff which might hang> 
} 
else { 
    #parent block 
    my $child_id = <PARENTRECEIVE>; 
    chomp $child_id; 
    <do parent stuff> 
    <if you think child is hung> { 
    kill 1, $child_id; 
    } 
} 

कभी-कभी हमारे वेब सर्वर रुक जाता है, तो मैं इस का उपयोग जांच करने के लिए करता है, तो यह अभी भी करने के लिए जवाब को देखने के लिए उचित समय में HTTP अनुरोध प्राप्त करें। बच्चे यूआरएल हथियाने से पहले माता-पिता की घड़ी निर्भर है समाप्त नहीं करता है, यह एक ई-मेल चेतावनी कहने के लिए कुछ है भेजता है।

संबंधित मुद्दे