+sub watch_imap_fetch_all ($$) {
+ my ($self, $uris) = @_;
+ for my $uri (@$uris) {
+ my $sec = imap_section($uri);
+ my $mic_arg = $self->{mic_arg}->{$sec} or
+ die "BUG: no Mail::IMAPClient->new arg for $sec";
+ my $mic = PublicInbox::IMAPClient->new(%$mic_arg) or next;
+ my $err = imap_fetch_all($self, $mic, $uri);
+ last if $self->{quit};
+ warn $err, "\n" if $err;
+ }
+}
+
+sub imap_fetch_fork ($$$) {
+ my ($self, $intvl, $uris) = @_;
+ return if $self->{quit};
+ $self->{mics} = {}; # going to be forking, so disconnect
+ defined(my $pid = fork) or die "fork: $!";
+ if ($pid == 0) {
+ watch_atfork_child($self);
+ watch_imap_fetch_all($self, $uris);
+ _exit(0);
+ }
+ $self->{poll_pids}->{$pid} = [ $intvl, $uris ];
+ PublicInbox::DS::dwaitpid($pid, \&imap_fetch_reap, $self);
+}
+
+sub imap_fetch_cb ($$$) {
+ my ($self, $intvl, $uris) = @_;
+ sub { imap_fetch_fork($self, $intvl, $uris) };
+}
+
+sub imap_fetch_reap { # PublicInbox::DS::dwaitpid callback
+ my ($self, $pid) = @_;
+ my $intvl_uris = delete $self->{poll_pids}->{$pid} or
+ die "BUG: PID=$pid (unknown) reaped: \$?=$?\n";
+ return if $self->{quit};
+ my ($intvl, $uris) = @$intvl_uris;
+ if ($?) {
+ warn "W: PID=$pid died: \$?=$?\n",
+ map { $_->as_string."\n" } @$uris;
+ }
+ warn('I: will check ', $_->as_string, " in ${intvl}s\n") for @$uris;
+ PublicInbox::DS::add_timer($intvl, imap_fetch_cb($self, $intvl, $uris));
+}
+