--- deliantra/Deliantra-Client/DC.pm 2006/10/01 14:48:50 1.122 +++ deliantra/Deliantra-Client/DC.pm 2006/10/09 01:06:36 1.123 @@ -64,6 +64,63 @@ $_ } +sub socketpipe() { + socketpair my $fh1, my $fh2, Socket::AF_UNIX, Socket::SOCK_STREAM, Socket::PF_UNSPEC + or die "cannot establish bidiretcional pipe: $!\n"; + + ($fh1, $fh2) +} + +sub background(&) { + my ($cb) = @_; + + my ($fh_r, $fh_w) = CFPlus::socketpipe; + + my $pid = fork; + + if (defined $pid && !$pid) { + $SIG{__DIE__} = sub { + my $msg = $_[0]; + $msg =~ s/\n+/\n/; + warn "FATAL: $msg"; + CFPlus::_exit 99; + }; + + open STDOUT, ">&", $fh_w; + open STDERR, ">&", $fh_w; + close $fh_r; + close $fh_w; + + $| = 1; + + $cb->(); + + # win32 is fucked up, of course. exit will clean stuff up, + # which destroys our database etc. _exit will exit ALL + # forked processes, because of the dreaded fork emulation. + CFPlus::_exit 0; + } + + close $fh_w; + + my $buffer; + + Event->io (fd => $fh_r, poll => 'r', cb => sub { + unless (sysread $fh_r, $buffer, 4096, length $buffer) { + $_[0]->w->cancel; + $buffer .= "done\n"; + } + + while ($buffer =~ s/^(.*)\n//) { + my $line = $1; + utf8::decode $line; + ::message ({ + markup => "editor($pid): " . CFPlus::asxml $line, + }); + } + }); +} + package CFPlus::Database; our @ISA = BerkeleyDB::Btree::;