我是perl中多进程编程过程的新手。我正在尝试编写一个基于多线程多进程的应用程序,它给了我“SEGMENTATION FAULT”。 该计划很简单。首先,PARENT PROCESS产生一些进程(使用fork),并且每个进程在一段时间后运行并在随机延迟后死亡。 同时,父进程产生相同数量的线程来监听每个新分叉的子进程。 我正在使用管道在分叉进程和从主进程生成的线程之间进行通信。 这里的想法是,当一个进程死掉时,另一个新进程应该立即生成相同的管道,因此在子程序调用之后会产生无限的while循环。 有时,这可以正常工作,但突然之间出现了分段错误。 我该如何调试这种情况? 我的PERL版本是5.8.8
#!/usr/local/bin/perl -w
use strict;
use threads;
use threads::shared;
use IO::Pipe;
use warnings;
print "Starting main program\n";
my $ACTIVE_PROCESSES :shared =0;
my $MAX_PROCESSES:shared =5,
my %process_state_list : shared;
my %process_id_list : shared;
$SIG{CHLD} = sub { wait };
my $GLOBAL_COUNT=0;
my @pipe_array=&share([]);
&init_pipes();
&spawn_process();
while(1)
{
for (my $i=0;$i<$MAX_PROCESSES;$i++)
{
if ($process_state_list{$i} =~ /INACTIVE/)
{
print "Found Process $i is inactive\n";
spawn_next_process($i);
}
}
}
print "End of main program from $$\n";
sub init_pipes
{
my $i=0;
for ($i=0;$i< $MAX_PROCESSES; $i++)
{
$pipe_array[$i] = IO::Pipe->new();
$process_state_list{$i}="INACTIVE";
print "Pipe $i initialized to $pipe_array[$i]\n";
}
}
sub spawn_process
{
print "Spawn process called..\n";
while ( $ACTIVE_PROCESSES < $MAX_PROCESSES)
{
$GLOBAL_COUNT++;
PARENT_create_child();
PARENT_create_child_listener();
}
}
sub PARENT_update_child_map
{
my ($i,$cmd)=@_;
if ($cmd =~ /CREATE/)
{
for (my $j=0;$j<$MAX_PROCESSES;$j++)
{
print "j is $j and process_state_list is $process_state_list{$j}\n";
if ($process_state_list{$j}=~ /INACTIVE/)
{
$process_state_list{$j}="ACTIVE";
return $j;
}
}
}
}
sub PARENT_create_child()
{
for (my $i=0;$i<$MAX_PROCESSES;$i++)
{
print"--------FORKING CHILD from MAIN PROCESS MAIN PID $$\n";
my $local_pr_id = PARENT_update_child_map($i,"CREATE");
my $pid = fork() ;
if ($pid) {
# parent
print "For local_pr_id $local_pr_id CHILD is $pid, PARENT $$\n";
$ACTIVE_PROCESSES++;
}
elsif ($pid == 0) {
# child
child_activator($local_pr_id);
exit 0;
} else {
die "couldnt fork: $!\n";
}
}
}
sub PARENT_create_child_listener()
{
print"--------THREADING CHILD LISTENER FROM--$$--\n";
my $i;
for ($i=0;$i<$MAX_PROCESSES;$i++)
{
my $worker_thread = threads->create(sub {\&read_from_child($i)});
$worker_thread->detach();
}
}
sub read_from_child
{
my $th=threads->self();
print"--------NOW THREADING:$th->tid()\n";
my ($pipe_index)=shift;
print "pipe_index is $pipe_index\n";
($pipe_array[$pipe_index])->reader();
my $filehandle=$pipe_array[$pipe_index];
while ( <$filehandle> ) {
my $msg=$_;
print "CHILD LISTENER received: $msg And current Process ID is $$\n";
PARENT_msg_from_child($msg);
}
print "Exiting read_from_child from $$\n";
}
sub PARENT_msg_from_child()
{
my $msg=shift;
if ($msg =~ /IPC_MSG_PROCESS_EXIT/)
{
PARENT_handle_IPC_MSG_PROCESS_EXIT($msg);
}
if ($msg=~ /IPC_MSG_PROCESS_START/)
{
PARENT_handle_IPC_MSG_PROCESS_START($msg);
}
}
sub PARENT_handle_IPC_MSG_PROCESS_START
{
my $msg=shift;
my @split_array=split(":",$msg);
my $local_pr_id=$split_array[1];
my $process_id=$split_array[2];
$process_state_list{$local_pr_id}="ACTIVE";
$process_id_list{$local_pr_id}=$process_id;
}
sub PARENT_handle_IPC_MSG_PROCESS_EXIT
{
my $msg=shift;
my @split_array=split(":",$msg);
my $local_pr_id=$split_array[1];
print "------------------------\n";
$ACTIVE_PROCESSES--;
$process_state_list{$local_pr_id}="INACTIVE";
my $exists = kill 0, $local_pr_id;
kill(9,$process_id_list{$local_pr_id}) if $exists;
print "Process $process_id_list{$local_pr_id} terminated\n";
}
sub spawn_next_process
{
my $local_pr_id= shift;
print"--------FORKING NEXT CHILD from MAIN PROCESS MAIN PID $$\n";
$process_state_list{$local_pr_id}="ACTIVE";
my $pid = fork() ;
if ($pid) {
# parent
print "For local_pr_id $local_pr_id CHILD is $pid, PARENT $$\n";
$ACTIVE_PROCESSES++;
}
elsif ($pid == 0) {
# child
child_activator($local_pr_id);
exit 0;
} else {
die "couldnt fork: $!\n";
}
}
#################C H I L D -- S E C T I O N####################
sub child_activator {
sleep (7);
my $local_pr_id=shift;
print "In child activator $$\n";
my $filehandle=$pipe_array[$local_pr_id] ;
($pipe_array[$local_pr_id])->writer();
my $message="IPC_MSG_PROCESS_START:$local_pr_id:$$:";
print "Sending $message\n";
print $filehandle $message
or die "Failed to pass message to child: $!";
my $random_number = rand();
sleep(4*$random_number);
print "Now in child process $$\n";
print "local_pr_id is $local_pr_id\n";
$message="IPC_MSG_PROCESS_EXIT:$local_pr_id:";
print "Sending $message\n";
print $filehandle $message
or die "Failed to pass message to child: $!";
}
################# E N D - C H I L D - S E C T I O N###########
我从这里获得的输出是非常需要的: -
<I>xl-mat-02{userxxx}141: perl run_tc.pl
Starting main program
Pipe 0 initialized to IO::Pipe=GLOB(0x169c4830)
Pipe 1 initialized to IO::Pipe=GLOB(0x168632a0)
Pipe 2 initialized to IO::Pipe=GLOB(0x169c4af0)
Pipe 3 initialized to IO::Pipe=GLOB(0x169c4bb0)
Pipe 4 initialized to IO::Pipe=GLOB(0x169c4c70)
Spawn process called..
--------FORKING CHILD from MAIN PROCESS MAIN PID 1520
j is 0 and process_state_list is INACTIVE
For local_pr_id 0 CHILD is 1598, PARENT 1520
--------FORKING CHILD from MAIN PROCESS MAIN PID 1520
j is 0 and process_state_list is ACTIVE
j is 1 and process_state_list is INACTIVE
For local_pr_id 1 CHILD is 1599, PARENT 1520
--------FORKING CHILD from MAIN PROCESS MAIN PID 1520
j is 0 and process_state_list is ACTIVE
j is 1 and process_state_list is ACTIVE
j is 2 and process_state_list is INACTIVE
For local_pr_id 2 CHILD is 1600, PARENT 1520
--------FORKING CHILD from MAIN PROCESS MAIN PID 1520
j is 0 and process_state_list is ACTIVE
j is 1 and process_state_list is ACTIVE
j is 2 and process_state_list is ACTIVE
j is 3 and process_state_list is INACTIVE
For local_pr_id 3 CHILD is 1601, PARENT 1520
--------FORKING CHILD from MAIN PROCESS MAIN PID 1520
j is 0 and process_state_list is ACTIVE
j is 1 and process_state_list is ACTIVE
j is 2 and process_state_list is ACTIVE
j is 3 and process_state_list is ACTIVE
j is 4 and process_state_list is INACTIVE
For local_pr_id 4 CHILD is 1602, PARENT 1520
--------THREADING CHILD LISTENER FROM--1520--
--------NOW THREADING:threads=SCALAR(0x16abfef0)->tid()
pipe_index is 0
--------NOW THREADING:threads=SCALAR(0x16b95010)->tid()
pipe_index is 1
--------NOW THREADING:threads=SCALAR(0x2aaaac0fdfb0)->tid()
pipe_index is 2
--------NOW THREADING:threads=SCALAR(0x2aaaac1e2770)->tid()
pipe_index is 3
--------NOW THREADING:threads=SCALAR(0x2aaaac2c7210)->tid()
pipe_index is 4
In child activator 1598
Sending IPC_MSG_PROCESS_START:0:1598:
In child activator 1599
Sending IPC_MSG_PROCESS_START:1:1599:
In child activator 1600
Sending IPC_MSG_PROCESS_START:2:1600:
In child activator 1601
Sending IPC_MSG_PROCESS_START:3:1601:
In child activator 1602
Sending IPC_MSG_PROCESS_START:4:1602:
Now in child process 1599
local_pr_id is 1
Now in child process 1600
local_pr_id is 2
Sending IPC_MSG_PROCESS_EXIT:2:
Sending IPC_MSG_PROCESS_EXIT:1:
Now in child process 1601
local_pr_id is 3
Sending IPC_MSG_PROCESS_EXIT:3:
***Segmentation fault***
xl-mat-02{userxxx}142: Now in child process 1598
local_pr_id is 0
Sending IPC_MSG_PROCESS_EXIT:0:
Now in child process 1602
local_pr_id is 4
Sending IPC_MSG_PROCESS_EXIT:4:</I>
我无法发现为什么会发生分裂错误。 就像我说的,我是多进程环境编程的新手。所以我可能错过了一些非常基本的东西。 任何帮助,将不胜感激。 即使您在这种情况下有分段错误的基本提示,请告诉我,因为我一无所知!