#! /usr/bin/perl use strict; use warnings; use threads; use Error qw(:try); use Data::Dumper; use Time::HiRes qw(time sleep); use Time::HiRes qw(time usleep); use Thread::Queue; use threads::shared; use POSIX ":sys_wait_h"; use IO::Handle; use SF::DBFork; my $DEAD_KIDS = 0; my %forks; my $maxKids = 5; sub Persistent() { my $parent = shift; my $count = 0; my $numkids = 0; while (1){ if ($numkids < $maxKids) { $parent->SendMessage(++$count); $numkids++; } my $q = $parent->ReceiveMessage(); if ($q) { chomp $q; $numkids--; warn "[P $$] Received message from parent:"; warn Dumper($q); } else { last; } } } sub Ephemeral() { my $q = shift; chomp $q; warn "[E $$] Received message from parent:"; warn Dumper($q); exit(); } $SIG{CHLD} = \&childHandler; sub childHandler { $DEAD_KIDS++; warn "-Caught SIGCHLD ($DEAD_KIDS) [$$]\n"; $SIG{CHLD} = \&childHandler; } sub Main() { my $persistent = SF::DBFork->new(\&Persistent); my $fid = $persistent->Spawn(1, 0); my $ephemeral = SF::DBFork->new(\&Ephemeral); while (1) { if ($DEAD_KIDS) { $DEAD_KIDS = 0; my $dead_kid; while (($dead_kid = waitpid(-1, WNOHANG)) > 0) { if ($dead_kid == $fid) { die "The persistent thread has died! I'm gonna quit!"; } else { my $q = $forks{$dead_kid}; warn "[M $$] Child $dead_kid ended."; if ($q) { warn "[M] Sending dead kid message."; $persistent->SendMessage($q); warn "[M] Message sent."; delete $forks{$dead_kid}; warn "[M] dead kid deleted from hash."; } } } } warn "[M] Going to ReceiveMessage"; my $q = $persistent->ReceiveMessage(1); warn "[M] Exiting ReceiveMessage"; if ($q) { $forks{$ephemeral->Spawn(0,1,$q)} = $q; } usleep(200 * 1000); } } Main();