From 49c809e0314fc91f786791f8492bd2f2a1d525d3 Mon Sep 17 00:00:00 2001 From: Jarrod Johnson Date: Wed, 27 May 2015 10:23:37 -0400 Subject: [PATCH] Reorganize UDP <-> SSL rework Because SSL actually was relying upon accept() to hold indefininetly, it would hang up the UDP worker indefinitely, blocking requests. Fix this by driving the loop iteration through select() rather than accept() and iterating through each file handle only when select() says they are ready. --- xCAT-server/sbin/xcatd | 27 +++++++++++++++++---------- 1 file changed, 17 insertions(+), 10 deletions(-) diff --git a/xCAT-server/sbin/xcatd b/xCAT-server/sbin/xcatd index 512716e31..548c58bb9 100755 --- a/xCAT-server/sbin/xcatd +++ b/xCAT-server/sbin/xcatd @@ -1099,6 +1099,7 @@ while (not $listener and $retry) { } my $listenwatcher = IO::Select->new($listener); my $udpwatcher = IO::Select->new($udpctl); +my $bothwatcher = IO::Select->new($udpctl, $listener); unless ($listener) { kill 2, $pid_UDP; @@ -1130,6 +1131,17 @@ my $tconn; my $sslfudgefactor = 0; until ($quit) { $SIG{CHLD} = \&ssl_reaper; #set here to ensure that signal handler is not corrupted during loop + while ($udpwatcher->can_read(0)) { # take an intermission to broker some state requests from udp traffic control + eval { + my $msg = fd_retrieve($udpctl); + if ($msg->{req} eq 'get_client_count') { + store_fd({'clientfudge'=>$sslfudgefactor, 'sslclientcount' => $sslclients}, $udpctl); + } elsif ($msg->{req} eq 'set_fudge_factor') { + $sslfudgefactor = $msg->{fudge}; + store_fd({'clientfudge'=>$sslfudgefactor, 'sslclientcount' => $sslclients}, $udpctl); + } + }; + } if (@pendingconnections) { while ($listenwatcher->can_read(0)) { #grab everything we can, but don't spend any time waiting for more $tconn = $listener->accept; @@ -1137,21 +1149,16 @@ until ($quit) { push @pendingconnections,$tconn; } } else { + $bothwatcher->can_read(30); + if (not $listenwatcher->can_read(0)) { # check for udpctl messages since + # we have no listen to hear + next; + } $tconn = $listener->accept; #we have no connections pending, no rush, just wait until the next connection attempt comes in unless ($tconn) { next; } #sometimes we get 'undef', in which case carry on with our lives... push @pendingconnections,$tconn; } unless (scalar @pendingconnections) { next; } #if for some reason we landed here without any accepted connections, carry on.. - while ($udpwatcher->can_read(0)) { # take an intermission to broker some state requests from udp traffic control - eval { - my $msg = fd_retrieve($udpctl); - if ($msg->{req} eq 'get_client_count') { - store_fd({'clientfudge'=>$sslfudgefactor, 'sslclientcount' => $sslclients}); - } elsif ($msg->{req} eq 'set_fudge_factor') { - $sslfudgefactor = $msg->{fudge}; - } - }; - } if ($sslclients > $maxsslclients) { #we have enough children, wait for some to exit before spawning more $listenwatcher->can_read(0.1); #when next connection tries to come in or a tenth of a second, whichever comes first next; #just keep pulling things off listen queue onto our own