From: minima Date: Sat, 9 Jun 2001 17:12:04 +0000 (+0000) Subject: fix both infinite recursion by detecting it X-Git-Url: http://dxcluster.org/gitweb/gitweb.cgi?a=commitdiff_plain;h=2edc1b59ddce231771947ff0f31adbae015ff6c7;p=spider.git fix both infinite recursion by detecting it fix the problem in route::config that caused it --- diff --git a/Changes b/Changes index 994e188d..4736c439 100644 --- a/Changes +++ b/Changes @@ -5,6 +5,8 @@ 3. add ephemera deduping for all those PC41,24,50 etc etc broadcasts 4. Fix a problem with the connect text being sent on outgoing connections (this confuses db0fhf amongst other things) +5. catch deep recursion bugs before you run out of memory. +6. Make sure that PC16|17|19|21 update as well as add and delete 08Jun01======================================================================= 1. first cut with new routing code. Created NEW_ROUTE branch 2. added acc/route and rej/route commands diff --git a/cmd/show/newconfiguration.pl b/cmd/show/newconfiguration.pl index a2599b88..66756191 100644 --- a/cmd/show/newconfiguration.pl +++ b/cmd/show/newconfiguration.pl @@ -16,6 +16,6 @@ if (@list && $list[0] =~ /^NOD/) { shift @list; } -push @out, $main::routeroot->config($nodes_only, 0, @list); +push @out, $main::routeroot->config($nodes_only, 0, [], @list); return (1, @out); diff --git a/perl/DXDebug.pm b/perl/DXDebug.pm index f7598c15..2cbdc295 100644 --- a/perl/DXDebug.pm +++ b/perl/DXDebug.pm @@ -70,7 +70,15 @@ sub dbginit { # add sig{__DIE__} handling if (!defined $DB::VERSION) { - $SIG{__WARN__} = sub { dbgstore($@, Carp::shortmess(@_)); }; + $SIG{__WARN__} = sub { + if ($_[0] =~ /Deep\s+recursion/i) { + dbgstore($@, Carp::longmess(@_)); + CORE::die; + } else { + dbgstore($@, Carp::shortmess(@_)); + } + }; + $SIG{__DIE__} = sub { dbgstore($@, Carp::longmess(@_)); }; } diff --git a/perl/DXProt.pm b/perl/DXProt.pm index a317fce2..6550f908 100644 --- a/perl/DXProt.pm +++ b/perl/DXProt.pm @@ -554,7 +554,15 @@ sub normal next unless $call && $conf && defined $here && is_callsign($call); $conf = $conf eq '*'; - push @rout, $parent->add_user($call, Route::here($here)|Route::conf($conf)); + my $r = Route::User::get($call); + my $flags = Route::here($here)|Route::conf($conf); + + if ($r && $r->flags != $flags) { + $r->$flags($flags); + push @rout, $r; + } elsif (!$r) { + push @rout, $parent->add_user($call, $flags); + } # add this station to the user database, if required $call =~ s/-\d+$//o; # remove ssid for users @@ -570,7 +578,6 @@ sub normal # queue up any messages (look for privates only) DXMsg::queue_msg(1) if $self->state eq 'normal'; - dbg('route', "B/C PC16 on $ncall for: " . join(',', map{$_->call} @rout)) if @rout; $self->route_pc16($parent, @rout) if @rout; return; } @@ -578,6 +585,7 @@ sub normal if ($pcno == 17) { # remove a user my $dxchan; my $ncall = $field[2]; + my $ucall = $field[1]; if ($ncall eq $main::mycall) { dbg('chan', "PCPROT: trying to alter config on this node from outside!"); return; @@ -592,8 +600,8 @@ sub normal dbg('chan', "PCPROT: Route::Node $ncall not in config"); return; } - my @rout = $parent->del_user($field[1]); - dbg('route', "B/C PC17 on $ncall for: $field[1]"); + my $r = Route::User::get($ucall); + my @rout = $parent->del_user($ucall) if $r; $self->route_pc17($parent, @rout) if @rout; return; } @@ -636,9 +644,10 @@ sub normal # update it if required my $r; - if ($parent->call eq $call && !$parent->version) { + my $flags = Route::here($here)|Route::conf($conf); + if ($parent->call eq $call && ($parent->version ne $ver || $parent->flags != $flags)) { $parent->version($ver); - $parent->flags(Route::here($here)|Route::conf($conf)); + $parent->flags($flags); push @rout, $parent; } elsif ($parent->call ne $call) { next if $call eq $main::mycall || $call eq $self->{call}; @@ -647,7 +656,7 @@ sub normal push @rout, $r if $r; } else { $r = Route::Node::get($call); - if ($r && (!$r->version || $r->version eq '0000')) { + if ($r && ($r->version ne $ver || $r->flags != $flags)) { $r->version($ver); $r->flags(Route::here($here)|Route::conf($conf)); push @rout, $r; @@ -672,8 +681,6 @@ sub normal $user->put; } - dbg('route', "B/C PC19 for: " . join(',', map{$_->call} @rout)) if @rout; - $self->route_pc19(@rout) if @rout; return; } @@ -706,8 +713,6 @@ sub normal dbg('chan', "PCPROT: I WILL _NOT_ be disconnected!"); return; } - dbg('route', "B/C PC21 for: " . join(',', (map{$_->call} @rout))) if @rout; - $self->route_pc21(@rout) if @rout; return; } @@ -1098,7 +1103,9 @@ sub process # send a pc50 out on this channel $dxchan->{pc50_t} = $main::systime unless exists $dxchan->{pc50_t}; if ($t >= $dxchan->{pc50_t} + $DXProt::pc50_interval) { - $dxchan->send(pc50(scalar DXChannel::get_all_users)); + my $s = pc50(scalar DXChannel::get_all_users); + eph_dup($s); + $dxchan->send($s); $dxchan->{pc50_t} = $t; } diff --git a/perl/Route.pm b/perl/Route.pm index e5d89828..b4306e04 100644 --- a/perl/Route.pm +++ b/perl/Route.pm @@ -155,6 +155,7 @@ sub config my $self = shift; my $nodes_only = shift; my $level = shift; + my $seen = shift; my @out; my $line; my $call = $self->user_call; @@ -168,6 +169,16 @@ sub config if ($printit) { $line = ' ' x ($level*2) . "$call"; $call = ' ' x length $call; + + # recursion detector + if ((DXChannel->get($self->{call}) && $level > 1) || grep $self->{call} eq $_, @$seen) { + $line .= ' ...'; + push @out, $line; + return @out; + } + push @$seen, $self->{call}; + + # print users unless ($nodes_only) { if (@{$self->{users}}) { $line .= '->'; @@ -194,12 +205,14 @@ sub config push @out, $line if length $line; } + # deal with more nodes foreach my $ncall (sort @{$self->{nodes}}) { my $nref = Route::Node::get($ncall); if ($nref) { my $c = $nref->user_call; - push @out, $nref->config($nodes_only, $level+1, @_); + dbg('routec', "recursing from $call -> $c"); + push @out, $nref->config($nodes_only, $level+1, $seen, @_); } else { push @out, ' ' x (($level+1)*2) . "$ncall?" if @_ == 0 || (@_ && grep $ncall =~ m|$_|, @_); }