From a4c66663c1808d18328d3bc096d7df0a1a80a9e6 Mon Sep 17 00:00:00 2001 From: Jeroen van Ingen Schenau Date: Wed, 18 Nov 2020 12:36:13 +0100 Subject: [PATCH] Don't add AUTOLOAD generated methods in symbol table (#409) (#410) When a method is resolved via AUTOLOAD (eg for objects defined in %FUNCS), adding the method to the symbol table leads to skipping AUTOLOAD on subsequent calls to the method. The method table however is global to the interpreter, so even when a new SNMP::Info instance is created for a different device, all methods created by a previous device are just "carried over" to the new one if they are put into the symbol table. This breaks a method like "v_name", which may resolve differently in different device classes, in the use case where devices from different classes are polled one after another (even if new SNMP::Info object instances are used every time). --- lib/SNMP/Info.pm | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/lib/SNMP/Info.pm b/lib/SNMP/Info.pm index 0f4deb81..6428d187 100644 --- a/lib/SNMP/Info.pm +++ b/lib/SNMP/Info.pm @@ -4989,8 +4989,7 @@ capabilities to include dynamic methods generated at run time via AUTOLOAD. Calls parent can() first to see if method exists, if not validates that a method should be created then dispatches to the appropriate internal method -for creation. The newly created method is inserted into the symbol table -returning to AUTOLOAD only for the initial method call. +for creation. Returns undef if the method does not exist and can not be created. @@ -5027,15 +5026,21 @@ sub can { # we’ll just create if/when they are called rather than pollute the # symbol table with entries that never get called. + # Between 2012-2020 we actually added the methods generated below to the + # symbol table, but they were global to the SNMP::Info class, while + # methods for different device classes may point to different SNMP + # objects. This made interacting with multiple device types from a single + # script somewhat unreliable. + # Check for set_ ing. if ( $method =~ /^set_/ ) { - return *{$method} = _make_setter( $method, $oid, @_ ); + return _make_setter( $method, $oid, @_ ); } elsif ( defined $funcs->{$base_method} || $table ) { - return *{$method} = _load_attr( $method, $oid, @_ ); + return _load_attr( $method, $oid, @_ ); } else { - return *{$method} = _global( $method, $oid ); + return _global( $method, $oid ); } } @@ -5044,9 +5049,7 @@ sub can { =head2 AUTOLOAD Each entry in either %FUNCS, %GLOBALS, or MIB Leaf node names present in -loaded MIBs are used by AUTOLOAD() to create dynamic methods. Generated -methods are inserted into the symbol table so that subsequent calls can avoid -AUTOLOAD() and dispatch directly. +loaded MIBs are used by AUTOLOAD() to create dynamic methods. =over