# API and build change and fix summaries. Doc correctsions
# and/or changes are not mentioned here; see the commit messages.
+2020 November 4; Version 4.4.4
+ Correct address memory leak in the RTE cleanup. (RIC-674)
+
2020 November 4; Version 4.4.3
Correct bug introduced with race fix (4.4.0) (RIC-674)
set( major_version "4" ) # should be automatically populated from git tag later, but until CI process sets a tag we use this
set( minor_version "4" )
-set( patch_level "3" )
+set( patch_level "4" )
set( install_root "${CMAKE_INSTALL_PREFIX}" )
set( install_inc "include/rmr" )
version 4.0.0, the RMR versions should no longer skip.
+2020 November 4; Version 4.4.4
+------------------------------
+
+Correct address memory leak in the RTE cleanup. (RIC-674)
+
+
+
2020 November 4; Version 4.4.3
------------------------------
rmr_sym_foreach_class( rt->hash, 1, ep_counts, id ); // run endpoints in the active table
}
+
+static void dump_tables( uta_ctx_t *ctx ) {
+ if( ctx->old_rtable != NULL ) {
+ rmr_vlog_force( RMR_VL_DEBUG, "old route table: (ref_count=%d)\n", ctx->old_rtable->ref_count );
+ rt_stats( ctx->old_rtable );
+ } else {
+ rmr_vlog_force( RMR_VL_DEBUG, "old route table was empty\n" );
+ }
+ rmr_vlog_force( RMR_VL_DEBUG, "new route table:\n" );
+ rt_stats( ctx->rtable );
+}
+
// ------------ route manager communication -------------------------------------------------
/*
Send a request for a table update to the route manager. Updates come in
}
if( ctx->new_rtable ) {
- if( DEBUG > 1 || (vlevel > 1) ) rmr_vlog( RMR_VL_DEBUG, "end of route table noticed\n" );
roll_tables( ctx ); // roll active to old, and new to active with proper locking
-
- if( vlevel > 0 ) {
- if( ctx->old_rtable != NULL ) {
- rmr_vlog_force( RMR_VL_DEBUG, "old route table: (ref_count=%d)\n", ctx->old_rtable->ref_count );
- rt_stats( ctx->old_rtable );
- } else {
- rmr_vlog_force( RMR_VL_DEBUG, "old route table was empty\n" );
- }
- rmr_vlog_force( RMR_VL_DEBUG, "new route table:\n" );
- rt_stats( ctx->rtable );
+ if( DEBUG > 1 || (vlevel > 1) ) {
+ rmr_vlog( RMR_VL_DEBUG, "end of route table noticed\n" );
+ dump_tables( ctx );
}
send_rt_ack( pctx, mbuf, ctx->table_id, RMR_OK, NULL );
if( ctx->new_rtable ) {
roll_tables( ctx ); // roll active to old, and new to active with proper locking
- if( DEBUG > 1 || (vlevel > 1) ) rmr_vlog_force( RMR_VL_DEBUG, "end of rt update noticed\n" );
-
- if( vlevel > 0 ) {
- if( ctx->old_rtable != NULL ) {
- rmr_vlog_force( RMR_VL_DEBUG, "old route table: (ref_count=%d)\n", ctx->old_rtable->ref_count );
- rt_stats( ctx->old_rtable );
- } else {
- rmr_vlog_force( RMR_VL_DEBUG, "old route table was empty\n" );
- }
- rmr_vlog_force( RMR_VL_DEBUG, "updated route table:\n" );
- rt_stats( ctx->rtable );
+ if( DEBUG > 1 || (vlevel > 1) ) {
+ rmr_vlog_force( RMR_VL_DEBUG, "end of rt update noticed\n" );
+ dump_tables( ctx );
}
send_rt_ack( pctx, mbuf, ctx->table_id, RMR_OK, NULL );
for( i = 0; i < rte->nrrgroups; i++ ) {
if( rte->rrgroups[i] ) {
free( rte->rrgroups[i]->epts ); // ditch list of endpoint pointers (end points are reused; don't trash them)
+ free( rte->rrgroups[i] ); // but must free the rrg itself too
}
+
}
free( rte->rrgroups );
return NULL;
}
- if( (ctx->ephash = rmr_sym_alloc( RT_SIZE )) == NULL ) { // master hash table for endpoints (each rt will reference this)
- rmr_vlog( RMR_VL_CRIT, "rmr_rtc: internal mishap: unable to allocate an endpoint hash table\n" );
- return NULL;
- }
-
if( (eptr = getenv( ENV_VERBOSE_FILE )) != NULL ) {
vfd = open( eptr, O_RDONLY );
vlevel = refresh_vlevel( vfd );
*(tok++) = 0;
}
- hent = gethostbyname( dname );
+ hent = gethostbyname( dname ); // valgrind will complain that this leaks, but we cannot free it!
if( hent == NULL || hent->h_addr_list == NULL ) {
//rmr_vlog( RMR_VL_WARN, "h2ip: dns lookup failed for: %s\n", dname );
free( dname );
Returns a transport struct which is the main context for the listener.
*/
extern struct tp_blk *SIlisten_prep( int type, char* abuf, int family ) {
- struct tp_blk *tptr; // pointer at new tp block
- int status = SI_OK; // processing status
+ struct tp_blk *tptr; // pointer at new tp block
struct sockaddr *addr; // IP address we are requesting
- int protocol; // protocol for socket call
int optval = 0;
int alen = 0;
+ int status = SI_OK; // processing status
+ int protocol; // protocol for socket call
- tptr = (struct tp_blk *) SInew( TP_BLK ); // new transport info block
+ tptr = (struct tp_blk *) SInew( TP_BLK ); // transport info
- if( tptr != NULL )
- {
+ if( tptr != NULL ) {
addr = NULL;
- switch( type ) // things specifc to tcp or udp
- {
- case UDP_DEVICE:
- tptr->type = SOCK_DGRAM;
- protocol = IPPROTO_UDP;
- break;
-
- case TCP_DEVICE:
- default:
- tptr->type = SOCK_STREAM;
- protocol = IPPROTO_TCP;
+ if( type == UDP_DEVICE ) {
+ tptr->type = SOCK_DGRAM;
+ protocol = IPPROTO_UDP;
+ } else {
+ tptr->type = SOCK_STREAM;
+ protocol = IPPROTO_TCP;
}
alen = SIgenaddr( abuf, protocol, family, tptr->type, &addr ); // family == 0 for type that suits the address passed in
}
SETSOCKOPT( tpptr->fd, SOL_TCP, TCP_QUICKACK, (void *)&optval, sizeof( optval) ) ;
- SIaddress( addr, (void **) &buf, AC_TODOT ); // get addr of remote side
- if( (cbptr = gptr->cbtab[SI_CB_SECURITY].cbrtn) != NULL ) { // invoke the security callback function if there
+ SIaddress( addr, (void **) &buf, AC_TODOT ); // get addr of remote side; buf must be freed
+ if( (cbptr = gptr->cbtab[SI_CB_SECURITY].cbrtn) != NULL ) { // invoke the security callback function if there
status = (*cbptr)( gptr->cbtab[SI_CB_SECURITY].cbdata, buf );
if( status == SI_RET_ERROR ) { // session to be rejected
SIterm( gptr, newtp ); // terminate new tp block (do NOT call trash)
SImap_fd( gptr, newtp->fd, newtp ); // add fd to the map
+ free( buf );
return SI_OK;
}