--- loncom/loncnew 2004/10/05 10:10:31 1.64 +++ loncom/loncnew 2004/10/05 11:16:57 1.65 @@ -2,7 +2,7 @@ # The LearningOnline Network with CAPA # lonc maintains the connections to remote computers # -# $Id: loncnew,v 1.64 2004/10/05 10:10:31 foxr Exp $ +# $Id: loncnew,v 1.65 2004/10/05 11:16:57 foxr Exp $ # # Copyright Michigan State University Board of Trustees # @@ -79,6 +79,8 @@ my %listening_to; # Socket->host table # is listening to. my %parent_dispatchers; # host-> listener watcher events. +my %parent_handlers; # Parent signal handlers... + my $MaxConnectionCount = 10; # Will get from config later. my $ClientConnection = 0; # Uniquifier for client events. @@ -87,6 +89,7 @@ my $NextDebugLevel= 2; # So Sigint can my $IdleTimeout= 600; # Wait 10 minutes before pruning connections. my $LogTransactions = 0; # When True, all transactions/replies get logged. +my $executable = $0; # Get the full path to me. # # The variables below are only used by the child processes. @@ -109,9 +112,8 @@ my $KeyMode = ""; # e.g. s my $LondConnecting = 0; # True when a connection is being built. -# DO NOT SET THE NEXT VARIABLE TO NON ZERO!!!!!!!!!!!!!!! -my $DieWhenIdle = 0; # When true children die when trimmed -> 0. +my $DieWhenIdle = 1; # When true children die when trimmed -> 0. my $I_am_child = 0; # True if this is the child process. # @@ -1650,9 +1652,19 @@ sub ChildProcess { Debug(5, "Killing watcher for $listener"); $watcher->cancel(); - undef $parent_dispatchers{$listener}; + delete($parent_dispatchers{$listener}); } + + # kill off the parent's signal handlers too! + # + + for my $handler (keys %parent_handlers) { + my $watcher = $parent_handlers{$handler}; + $watcher->cancel(); + delete($parent_handlers{$handler}); + } + $I_am_child = 1; # Seems like in spite of it all I may still getting # parent event dispatches.. flag I'm a child. @@ -1965,6 +1977,28 @@ if ($DieWhenIdle) { signal => "CHLD"); + # Set up all the other signals we set up. We'll vector them off to the + # same subs as we would for DieWhenIdle false and, if necessary, conditionalize + # the code there. + + $parent_handlers{INT} = Event->signal(cb => \&Terminate, + desc => "Parent INT handler", + signal => "INT"); + $parent_handlers{TERM} = Event->signal(cb => \&Terminate, + desc => "Parent TERM handler", + signal => "TERM"); + $parent_handlers{HUP} = Event->signal(cb => \&Restart, + desc => "Parent HUP handler.", + signal => "HUP"); + $parent_handlers{USR1} = Event->signal(cb => \&CheckKids, + desc => "Parent USR1 handler", + signal => "USR1"); + $parent_handlers{USR2} = Event->signal(cb => \&UpdateKids, + desc => "Parent USR2 handler.", + signal => "USR2"); + + # Start procdesing events. + $Event::DebugLevel = $DebugLevel; Debug(9, "Parent entering event loop"); my $ret = Event::loop(); @@ -2016,11 +2050,15 @@ sub CheckKids { my $now=time; my $local=localtime($now); print $fh "LONC status $local - parent $$ \n\n"; + foreach my $host (keys %parent_dispatchers) { + print $fh "LONC Parent process listening for $host\n"; + } foreach my $pid (keys %ChildHash) { Debug(2, "Sending USR1 -> $pid"); kill 'USR1' => $pid; # Tell Child to report status. sleep 1; # Wait so file doesn't intermix. } + } =pod @@ -2053,81 +2091,15 @@ sub UpdateKids { Log("INFO", "Updating connections via SIGUSR2"); - # Just in case we need to kill our own lonc, we wait a few seconds to - # give it a chance to receive and relay lond's response to the - # re-init command. - # - - sleep(2); # Wait a couple of seconds. + # I'm not sure what I was thinking in the first implementation. + # someone will have to work hard to convince me the effect is any + # different than Restart, especially now that we don't start up + # per host servers automatically, may as well just restart. + # The down side is transactions that are in flight will get timed out + # (lost unless they are critical). - my %hosts; # Indexed by loncapa hostname, value=ip. - - # Need to re-read the host table: - - - LondConnection::ReadConfig(); - my $I = LondConnection::GetHostIterator; - while (! $I->end()) { - my $item = $I->get(); - $hosts{$item->[0]} = $item->[4]; - $I->next(); - } + &Restart(); - # The logic below is written for clarity not for efficiency. - # Since I anticipate that this function is only rarely called, that's - # appropriate. There are certainly ways to combine the loops below, - # and anyone wishing to obscure the logic is welcome to go for it. - # Note that we don't re-direct sigchild. Instead we do what's needed - # to the data structures that keep track of children to ensure that - # when sigchild is honored, no new child is born. - # - - # For each existing child; if it's host doesn't exist, kill the child. - - foreach my $child (keys %ChildHash) { - my $oldhost = $ChildHash{$child}; - if (!(exists $hosts{$oldhost})) { - Log("CRITICAL", "Killing child for $oldhost host no longer exists"); - delete $ChildHash{$child}; - delete $HostToPid{$oldhost}; - kill 'QUIT' => $child; - } - } - # For each remaining existing child; if it's host's ip has changed, - # Restart the child on the new IP. - - foreach my $child (keys %ChildHash) { - my $oldhost = $ChildHash{$child}; - my $oldip = $HostHash{$oldhost}; - if ($hosts{$oldhost} ne $oldip) { - - # kill the old child. - - Log("CRITICAL", "Killing child for $oldhost host ip has changed..."); - delete $ChildHash{$child}; - delete $HostToPid{$oldhost}; - kill 'QUIT' => $child; - - # Do the book-keeping needed to start a new child on the - # new ip. - - $HostHash{$oldhost} = $hosts{$oldhost}; - CreateChild($oldhost); - } - } - # Finally, for each new host, not in the host hash, create a - # enter the host and create a new child. - # Force a status display of any existing process. - - foreach my $host (keys %hosts) { - if(!(exists $HostHash{$host})) { - Log("INFO", "New host $host discovered in hosts.tab..."); - $HostHash{$host} = $hosts{$host}; - CreateChild($host); - } else { - kill 'HUP' => $HostToPid{$host}; # status display. - } - } } @@ -2146,7 +2118,7 @@ sub Restart { Log("CRITICAL", "Restarting"); my $execdir = $perlvar{'lonDaemons'}; unlink("$execdir/logs/lonc.pid"); - exec("$execdir/loncnew"); + exec("$executable"); } =pod