Process shutdown can be chaotic and unpredictable.  Try to make
it more predictable by ensuring any PublicInbox::Select object
can't hold references to any objects.

This should fix the following error I saw in syslog during a deploy:

        Can't call method "FILENO" on an undefined value at
        .../PublicInbox/Select.pm line 34 during global destruction.

Replacing $Poller with PublicInbox::Select (instead of undef-ing
it) means we can avoid adding branches to ->epwait and ->close
before calls to ->ep_mod and ->ep_del, respectively.
---
 lib/PublicInbox/DS.pm | 10 +++++++---
 1 file changed, 7 insertions(+), 3 deletions(-)

diff --git a/lib/PublicInbox/DS.pm b/lib/PublicInbox/DS.pm
index d8824a55..e085a010 100644
--- a/lib/PublicInbox/DS.pm
+++ b/lib/PublicInbox/DS.pm
@@ -69,7 +69,11 @@ Reset all state
 sub Reset {
        do {
                $in_loop = undef; # first in case DESTROY callbacks use this
-               %DescriptorMap = ();
+               # clobbering $Poller may call DSKQXS::DESTROY,
+               # we must always have this set to something to avoid
+               # needing branches before ep_del/ep_mod calls (via ->close).
+               $Poller = PublicInbox::Select->new;
+               %DescriptorMap = (); # likely to call ep_del
                @Timers = ();
                %UniqTimer = ();
                @post_loop_do = ();
@@ -77,8 +81,8 @@ sub Reset {
                # we may be iterating inside one of these on our stack
                my @q = delete @Stack{keys %Stack};
                for my $q (@q) { @$q = () }
-               $AWAIT_PIDS = $nextq = $ToClose = undef;
-               $Poller = undef; # may call DSKQXS::DESTROY
+               $AWAIT_PIDS = $nextq = $ToClose = undef; # may call ep_del
+               $Poller = PublicInbox::Select->new;
        } while (@Timers || keys(%Stack) || $nextq || $AWAIT_PIDS ||
                $ToClose || keys(%DescriptorMap) ||
                @post_loop_do || keys(%UniqTimer));

Reply via email to