Skip site navigation (1)Skip section navigation (2)
Date:      10 Jun 1998 21:41:08 -0500
From:      sfarrell@farrell.org
To:        freebsd hackers <hackers@FreeBSD.ORG>
Subject:   perl forking causes panic in 2.2.6-stable
Message-ID:  <87bts0lkxn.fsf@couatl.uchicago.edu>

next in thread | raw e-mail | index | archive | help

tom christiansen posted a nifty prime number generator script that
uses forking to approximate threads [attached below].

i decided it was a little bit boring at only find primes under 1000,
so i upped the number to 5000.

unfortunately this panics my machine!  the panic is get_pv_entry:
cannot get a pv_entry_t.  i tried a less creative fork bomb with sh
and noticed that it gives "cannot fork", causes significant denial of
service, but can be killed and does not panic.

sparc/solaris gives an error: can't pipe: too many open files...,
but no panic.

FreeBSD 2.2.6-STABLE #0: Mon Jun  8 21:58:37 CDT 1998 

-------------------------------------------------------------------

#!/usr/bin/perl
# prime-fork: use sugalskd's thread algorithm 
# but with real processes.

sub main;
sub check_num;
sub forksub(&);
sub queue;
sub enqueue(*$);
sub dequeue(*);

use strict;
main();
exit;

sub main { 
    pipe(UPSTREAM, DOWNSTREAM);
    my($head,$tail) = queue();
    my $kid = forksub { 
	close($tail); 
	check_num($head, 2) 
    };
    close $head;
    for (my $i = 3; $i <= 5000; $i++) {
	enqueue($tail, $i);
    } 
    close $tail;
    waitpid($kid,0);
}

sub check_num {
    my ($stream, $cur_prime) = @_;
    my ($spawned, $num);

    my($head, $tail) = queue();

    while ($num = dequeue($stream) ) {
	next unless $num % $cur_prime;
	if ($spawned) { 
	    enqueue($tail, $num);
	    next;
	}
	print "Found prime $num\n";
	$spawned = forksub { 
	    close($tail); 
	    check_num($head, $num) 
	};
	close $head;
    } 
    close($head)  		unless $spawned;
    close($tail);
    waitpid($spawned,0) 	if     $spawned;
    exit;
}

sub forksub(&) {
    my $coderef = $_[0];
    my $pid = fork();
    die "cannot fork: $!" 	unless defined $pid;
    return $pid if $pid;
    goto &$coderef;		# don't need no stinkin' stack frames
} 

sub queue {
    local(*READER, *WRITER);
    pipe(READER, WRITER) || die "can't pipe: $!";
    return (*READER, *WRITER);
} 

sub enqueue(*$) {
    my ($stream, $n) = @_;
    syswrite($stream, pack("L", $n), 4);  # XXX: errno
} 

sub dequeue(*) {
    my ($stream) = @_;
    my $n;
    sysread($stream, $n, 4) == 4 || return;
    unpack("L", $n);
} 


--

Steve Farrell


To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-hackers" in the body of the message



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?87bts0lkxn.fsf>