Leaking these pipes to child processes wasn't harmful, but
made determining relationships and dataflow between processes
more confusing.
close $lockfh or die "close lock failed: $!";
}
close $lockfh or die "close lock failed: $!";
}
+sub atfork_child {
+ my ($self) = @_;
+ foreach my $f (qw(in out)) {
+ close $self->{$f} or die "failed to close import[$f]: $!\n";
+ }
+}
+
my $pid = fork;
defined $pid or die "fork failed: $!\n";
if ($pid == 0) {
my $pid = fork;
defined $pid or die "fork failed: $!\n";
if ($pid == 0) {
- foreach my $other (@{$v2writable->{idx_parts}}) {
- my $other_w = $other->{w} or next;
- close $other_w or die "close other failed: $!\n";
- }
+ $v2writable->atfork_child;
$v2writable = undef;
close $w;
$v2writable = undef;
close $w;
$w->flush or die "failed to flush: $!\n";
}
$w->flush or die "failed to flush: $!\n";
}
+sub atfork_child {
+ close $_[0]->{w} or die "failed to close write pipe: $!\n";
+}
+
use Storable qw(freeze thaw);
sub new {
use Storable qw(freeze thaw);
sub new {
- my ($class, $v2ibx) = @_;
- my $self = $class->SUPER::new($v2ibx, 1, 'all');
+ my ($class, $v2writable) = @_;
+ my $self = $class->SUPER::new($v2writable->{-inbox}, 1, 'all');
# create the DB:
$self->_xdb_acquire;
$self->_xdb_release;
# create the DB:
$self->_xdb_acquire;
$self->_xdb_release;
my $pid = fork;
defined $pid or die "fork failed: $!\n";
if ($pid == 0) {
my $pid = fork;
defined $pid or die "fork failed: $!\n";
if ($pid == 0) {
+ $v2writable->atfork_child;
+ $v2writable = undef;
close $w;
eval { thread_worker_loop($self, $r) };
die "thread worker died: $@\n" if $@;
close $w;
eval { thread_worker_loop($self, $r) };
die "thread worker died: $@\n" if $@;
sub idx_init {
my ($self) = @_;
return if $self->{idx_parts};
sub idx_init {
my ($self) = @_;
return if $self->{idx_parts};
- # first time initialization:
- my $all = $self->{all} =
- PublicInbox::SearchIdxThread->new($self->{-inbox});
+
+ # first time initialization, first we create the threader pipe:
+ my $all = $self->{all} = PublicInbox::SearchIdxThread->new($self);
# need to create all parts before initializing msgmap FD
my $max = $self->{partitions} - 1;
# need to create all parts before initializing msgmap FD
my $max = $self->{partitions} - 1;
for my $i (0..$max) {
push @$idx, PublicInbox::SearchIdxPart->new($self, $i, $all);
}
for my $i (0..$max) {
push @$idx, PublicInbox::SearchIdxPart->new($self, $i, $all);
}
+
+ # Now that all subprocesses are up, we can open the FD for SQLite:
$all->_msgmap_init->{dbh}->begin_work;
}
$all->_msgmap_init->{dbh}->begin_work;
}
+sub atfork_child {
+ my ($self) = @_;
+ if (my $parts = $self->{idx_parts}) {
+ $_->atfork_child foreach @$parts;
+ }
+ if (my $im = $self->{im}) {
+ $im->atfork_child;
+ }
+}
+