My crash issue stems from iinfo->free_data_context cb being called repeatedly with the same address to free. Any thoughts? thanksIan
----- Forwarded Message ----- From: Ian C via Net-snmp-coders <net-snmp-coders@lists.sourceforge.net>To: net-snmp-coders@lists.sourceforge.net <net-snmp-coders@lists.sourceforge.net>Sent: Tuesday, August 25, 2020, 3:20:07 p.m. EDTSubject: Table Iterator Crashes in free_data_context I'm still having a crash issue with my table agent, I can't figure out a solution, hoping the list members could help. In a nutshell I want to read a QNX pps object (file) each time (no caching) it is queried (snmpwalk). The data gets read and returned but a crash happens on the free (datactx). I would really appreciate a hand. thanks,Ian Net-Snmp 5.9QNX 7.1 /* * Note: this file originally auto-generated by mib2c using * : mib2c.iterate.conf 19302 2010-08-13 12:19:42Z dts12 $ */ /* generated from net-snmp-config */ extern "C" { #include <net-snmp/net-snmp-config.h> #include <net-snmp/net-snmp-includes.h> #include <net-snmp/agent/net-snmp-agent-includes.h> #include "chAsinHwSbcNtpTable.h" #include <syslog.h> #include <string.h> } void populateLocalSNMPstruct( struct chAsinHwSbcNtpTable_entry **table, const char channel ); /** Initializes the chAsinHwSbcNtpTable module */ extern "C" void init_chAsinHwSbcNtpTable(void) { /* here we initialize all the tables we're planning on supporting */ //syslog( LOG_DEBUG, "init_chAsinHwSbcNtpTable()"); initialize_table_chAsinHwSbcNtpTable(); } // # Determine the first/last column names void nsModuleTable_loop_free(void *context, netsnmp_iterator_info *dont_care) { free(context); } void freeTableEntry( void *data_context, netsnmp_iterator_info *useless ) { if (data_context != NULL) { free(data_context); <<<<<<<==== CRASHES HERE ON 1st CALL } return; } /** Initialize the chAsinHwSbcNtpTable table by defining its contents and how it's structured */ void initialize_table_chAsinHwSbcNtpTable(void) { //syslog( LOG_ERR, "initialize_table_chAsinHwSbcNtpTable()"); const oid chAsinHwSbcNtpTable_oid[] = {1,3,6,1,4,1,12345,3,3,1,9,6,6}; // 12345 is fictitious const size_t chAsinHwSbcNtpTable_oid_len = OID_LENGTH(chAsinHwSbcNtpTable_oid); netsnmp_handler_registration *reg; netsnmp_iterator_info *iinfo; netsnmp_table_registration_info *table_info; DEBUGMSGTL(("chAsinHwSbcNtpTable:init", "initializing table chAsinHwSbcNtpTable\n")); reg = netsnmp_create_handler_registration( "chAsinHwSbcNtpTable", chAsinHwSbcNtpTable_handler, chAsinHwSbcNtpTable_oid, chAsinHwSbcNtpTable_oid_len, HANDLER_CAN_RONLY ); table_info = SNMP_MALLOC_TYPEDEF( netsnmp_table_registration_info ); netsnmp_table_helper_add_indexes(table_info, ASN_OCTET_STR, /* index: chAsinHwSbcNtpSbcName */ 0); table_info->min_column = COLUMN_CHASINHWSBCNTPSBCNAME; table_info->max_column = COLUMN_CHASINHWSBCNTPSTATUSSTRING; iinfo = SNMP_MALLOC_TYPEDEF( netsnmp_iterator_info ); iinfo->get_first_data_point = chAsinHwSbcNtpTable_get_first_data_point; iinfo->get_next_data_point = chAsinHwSbcNtpTable_get_next_data_point; iinfo->table_reginfo = table_info; iinfo->free_loop_context_at_end = nsModuleTable_loop_free; iinfo->free_data_context = freeTableEntry; // <<<<<<==== MEM LEAK WITHOUT THIS! netsnmp_register_table_iterator( reg, iinfo ); /* Initialise the contents of the table here */ } struct chAsinHwSbcNtpTable_entry *chAsinHwSbcNtpTable_head; /* create a new row in the (unsorted) table */ struct chAsinHwSbcNtpTable_entry * chAsinHwSbcNtpTable_createEntry( char* chAsinHwSbcNtpSbcName, size_t chAsinHwSbcNtpSbcName_len ) { struct chAsinHwSbcNtpTable_entry *entry; entry = SNMP_MALLOC_TYPEDEF(struct chAsinHwSbcNtpTable_entry); if (!entry) return NULL; memcpy(entry->chAsinHwSbcNtpSbcName, chAsinHwSbcNtpSbcName, chAsinHwSbcNtpSbcName_len); entry->chAsinHwSbcNtpSbcName_len = chAsinHwSbcNtpSbcName_len; entry->next = chAsinHwSbcNtpTable_head; chAsinHwSbcNtpTable_head = entry; return entry; } /* remove a row from the table */ void chAsinHwSbcNtpTable_removeEntry( struct chAsinHwSbcNtpTable_entry *entry ) { struct chAsinHwSbcNtpTable_entry *ptr, *prev; if (!entry) return; /* Nothing to remove */ for ( ptr = chAsinHwSbcNtpTable_head, prev = NULL; ptr != NULL; prev = ptr, ptr = ptr->next ) { if ( ptr == entry ) break; } if ( !ptr ) return; /* Can't find it */ if ( prev == NULL ) chAsinHwSbcNtpTable_head = ptr->next; else prev->next = ptr->next; SNMP_FREE( entry ); /* XXX - release any other internal resources */ } /* Example iterator hook routines - using 'get_next' to do most of the work */ netsnmp_variable_list * chAsinHwSbcNtpTable_get_first_data_point(void **my_loop_context, void **my_data_context, netsnmp_variable_list *put_index_data, netsnmp_iterator_info *mydata) { populateLocalSNMPstruct( &chAsinHwSbcNtpTable_head, 'A' ); // collect NTP data for channel 'A' *my_loop_context = chAsinHwSbcNtpTable_head; return chAsinHwSbcNtpTable_get_next_data_point(my_loop_context, my_data_context, put_index_data, mydata ); } netsnmp_variable_list * chAsinHwSbcNtpTable_get_next_data_point(void **my_loop_context, void **my_data_context, netsnmp_variable_list *put_index_data, netsnmp_iterator_info *mydata) { struct chAsinHwSbcNtpTable_entry *entry = (struct chAsinHwSbcNtpTable_entry *)*my_loop_context; netsnmp_variable_list *idx = put_index_data; if ( entry ) { snmp_set_var_value( idx, entry->chAsinHwSbcNtpSbcName, sizeof(entry->chAsinHwSbcNtpSbcName) ); idx = idx->next_variable; *my_data_context = (void *)entry; *my_loop_context = (void *)entry->next; return put_index_data; } else { return NULL; } } /** handles requests for the chAsinHwSbcNtpTable table */ int chAsinHwSbcNtpTable_handler( netsnmp_mib_handler *handler, netsnmp_handler_registration *reginfo, netsnmp_agent_request_info *reqinfo, netsnmp_request_info *requests) { netsnmp_request_info *request; netsnmp_table_request_info *table_info; struct chAsinHwSbcNtpTable_entry *table_entry; DEBUGMSGTL(("chAsinHwSbcNtpTable:handler", "Processing request (%d)\n", reqinfo->mode)); switch (reqinfo->mode) { /* * Read-support (also covers GetNext requests) */ case MODE_GET: for (request=requests; request; request=request->next) { table_entry = (struct chAsinHwSbcNtpTable_entry *) netsnmp_extract_iterator_context(request); table_info = netsnmp_extract_table_info( request); switch (table_info->colnum) { case COLUMN_CHASINHWSBCNTPSBCNAME: if ( !table_entry ) { netsnmp_set_request_error(reqinfo, request, SNMP_NOSUCHINSTANCE); continue; } snmp_set_var_typed_value( request->requestvb, ASN_OCTET_STR, table_entry->chAsinHwSbcNtpSbcName, table_entry->chAsinHwSbcNtpSbcName_len); break; case COLUMN_CHASINHWSBCNTPSTATUSSTRING: if ( !table_entry ) { netsnmp_set_request_error(reqinfo, request, SNMP_NOSUCHINSTANCE); continue; } snmp_set_var_typed_value( request->requestvb, ASN_OCTET_STR, table_entry->chAsinHwSbcNtpStatusString, table_entry->chAsinHwSbcNtpStatusString_len); break; default: netsnmp_set_request_error(reqinfo, request, SNMP_NOSUCHOBJECT); break; } } break; } return SNMP_ERR_NOERROR; } // ==================================================================================================== // Populate the given Net-Snmp-generated struct with PPS data, in this case we want all /pps/ntp // data from all SBCs of the given channel. // void populateLocalSNMPstruct( struct chAsinHwSbcNtpTable_entry **table, const char channel ) { std::list< fpair_type > allSbcNtps; // full path, sbc name // For testing/dev only one file to read... allSbcNtps.push_back( std::make_pair( "/pps/ntp", "A1" )); // pps is QNX-specific, think of it as a file // process the list of paths extracting the json formatted ntp data struct chAsinHwSbcNtpTable_entry * tail, * head; head = NULL; tail = NULL; BOOST_FOREACH( const fpair_type & s, allSbcNtps ) { // open, read and close pps object char ppsData[2000]; readFile( s.first.c_str(), ppsData, sizeof( ppsData )); // readFile reads entire pps/file in one shot (impl not included here) std::string json( ppsData ); // get rid of all lines before json line (which starts with "sources:" size_t pos; if( std::string::npos != ( pos = json.find("sources:"))) { json.erase( 0, pos ); } // get rid of all lines after the json line (which ends with "}]}" if( std::string::npos != ( pos = json.find("}]}"))) { json.erase( pos + strlen("}]}") ); } // at this point ppsData is of the form "sources:json:{"data":[{...}]} // the 'sources:json:' isn't actually part of our json data, it's the way QNX PPS objects identify json data, so strip it away json.erase( 0, strlen("sources:json:")); struct chAsinHwSbcNtpTable_entry * current; current = reinterpret_cast< chAsinHwSbcNtpTable_entry *>( SNMP_MALLOC_TYPEDEF( struct chAsinHwSbcNtpTable_entry )); strncpy( current->chAsinHwSbcNtpStatusString, json.c_str(), JSONSIZE ); current->chAsinHwSbcNtpStatusString_len = json.size(); strncpy( current->chAsinHwSbcNtpSbcName, s.second.c_str(), NAMESIZE ); current->chAsinHwSbcNtpSbcName_len = s.second.size(); current->next = NULL; if( head == NULL ) { head = current; } else { tail->next = current; } tail = current; } *table = head; } _______________________________________________ Net-snmp-coders mailing list Net-snmp-coders@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/net-snmp-coders
_______________________________________________ Net-snmp-coders mailing list Net-snmp-coders@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/net-snmp-coders