Skip to content

Commit

Permalink
tools/nut-scanner/*.c: refactor nutscan_free() to actively lt_dlclose…
Browse files Browse the repository at this point in the history
…() the loaded library modules [networkupstools#2511]

Avoid some memory leak reports

Signed-off-by: Jim Klimov <[email protected]>
  • Loading branch information
jimklimov committed Jul 11, 2024
1 parent 6cb572d commit f2e9229
Show file tree
Hide file tree
Showing 8 changed files with 219 additions and 16 deletions.
2 changes: 1 addition & 1 deletion tools/nut-scanner/nut-scanner.c
Original file line number Diff line number Diff line change
Expand Up @@ -1886,8 +1886,8 @@ int main(int argc, char *argv[])
#endif

upsdebugx(1, "SCANS DONE: free common scanner resources");
nutscan_free();
nutscan_free_ip_ranges(&ip_ranges_list);
nutscan_free();

upsdebugx(1, "SCANS DONE: EXIT_SUCCESS");
return EXIT_SUCCESS;
Expand Down
78 changes: 65 additions & 13 deletions tools/nut-scanner/nutscan-init.c
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,11 @@
# if defined HAVE_WINSOCK2_H && HAVE_WINSOCK2_H
# include <winsock2.h>
# endif
#endif

/* FIXME: We may want to (also?) use lt_dlopenext(), so
* that libtool would offer platform-specific extensions */
#ifdef WIN32
# define SOEXT ".dll"
#else
# ifdef NUT_PLATFORM_APPLE_OSX
Expand All @@ -61,12 +66,19 @@ int nutscan_avail_snmp = 0;
int nutscan_avail_usb = 0;
int nutscan_avail_xml_http = 0;

/* Methods defined in scan_*.c source files */
int nutscan_load_usb_library(const char *libname_path);
int nutscan_unload_usb_library(void);
int nutscan_load_snmp_library(const char *libname_path);
int nutscan_unload_snmp_library(void);
int nutscan_load_neon_library(const char *libname_path);
int nutscan_unload_neon_library(void);
int nutscan_load_avahi_library(const char *libname_path);
int nutscan_unload_avahi_library(void);
int nutscan_load_ipmi_library(const char *libname_path);
int nutscan_unload_ipmi_library(void);
int nutscan_load_upsclient_library(const char *libname_path);
int nutscan_unload_upsclient_library(void);

#ifdef HAVE_PTHREAD
# ifdef HAVE_SEMAPHORE
Expand Down Expand Up @@ -586,27 +598,67 @@ void nutscan_init(void)
nutscan_avail_nut_simulation = 1;
}

void nutscan_free(void)
/* return 0 on success, -1 on error e.g. "was not loaded";
* other values may be possible if lt_dlclose() errors set them;
* visible externally to scan_* modules */
int nutscan_unload_library(int *avail, lt_dlhandle *pdl_handle, char **libpath);
int nutscan_unload_library(int *avail, lt_dlhandle *pdl_handle, char **libpath)
{
if (nutscan_avail_usb) {
lt_dlexit();
int ret = -1;

if (avail == NULL || pdl_handle == NULL) {
upsdebugx(1, "%s: called with bad inputs, no-op", __func__);
return -2;
}
if (nutscan_avail_snmp) {
lt_dlexit();

/* never tried/already unloaded */
if (*pdl_handle == NULL) {
goto end;
}
if (nutscan_avail_xml_http) {
lt_dlexit();

/* if previous init failed */
if (*pdl_handle == (void *)1) {
goto end;
}
if (nutscan_avail_avahi) {
lt_dlexit();

if (*avail == 0) {
upsdebugx(1, "%s: Asked to unload a module %p "
"for %s but our flag says it is not loaded",
__func__, (void *)(*pdl_handle),
(libpath && *libpath && **libpath)
? *libpath
: "<unidentified module>");
}
if (nutscan_avail_ipmi) {
lt_dlexit();

/* init has already been done */
if (libpath && *libpath && **libpath) {
upsdebugx(1, "%s: unloading module %s",
__func__, *libpath);
}
if (nutscan_avail_nut) {
lt_dlexit();
ret = lt_dlclose(*pdl_handle);
lt_dlexit();

end:
*pdl_handle = NULL;
*avail = 0;

if (libpath && *libpath) {
free(*libpath);
*libpath = NULL;
}

return ret;
}

void nutscan_free(void)
{
nutscan_unload_usb_library();
nutscan_unload_snmp_library();
nutscan_unload_neon_library();
nutscan_unload_avahi_library();
nutscan_unload_ipmi_library();
nutscan_unload_upsclient_library();

#ifdef HAVE_PTHREAD
/* TOTHINK: See comments near mutex/semaphore init code above */
# ifdef HAVE_SEMAPHORE
Expand Down
25 changes: 25 additions & 0 deletions tools/nut-scanner/scan_avahi.c
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@
#include "common.h"
#include "nut-scan.h"

/* externally visible to nutscan-init */
int nutscan_unload_avahi_library(void);

#ifdef WITH_AVAHI

#include <stdio.h>
Expand All @@ -48,6 +51,7 @@
/* dynamic link library stuff */
static lt_dlhandle dl_handle = NULL;
static const char *dl_error = NULL;
static char *dl_saved_libname = NULL;

static AvahiClient* (*nut_avahi_service_browser_get_client)(AvahiServiceBrowser *);
static int (*nut_avahi_simple_poll_loop)(AvahiSimplePoll *s);
Expand Down Expand Up @@ -91,6 +95,15 @@ static int (*nut_avahi_service_browser_free)(AvahiServiceBrowser *);
static char * (*nut_avahi_address_snprint)(char *ret_s, size_t length, const AvahiAddress *a);
static const AvahiPoll* (*nut_avahi_simple_poll_get)(AvahiSimplePoll *s);

/* return 0 on success, -1 on error e.g. "was not loaded";
* other values may be possible if lt_dlclose() errors set them;
* visible externally */
int nutscan_unload_library(int *avail, lt_dlhandle *pdl_handle, char **libpath);
int nutscan_unload_avahi_library(void)
{
return nutscan_unload_library(&nutscan_avail_avahi, &dl_handle, &dl_saved_libname);
}

/* return 0 on error; visible externally */
int nutscan_load_avahi_library(const char *libname_path);
int nutscan_load_avahi_library(const char *libname_path)
Expand Down Expand Up @@ -210,13 +223,21 @@ int nutscan_load_avahi_library(const char *libname_path)
goto err;
}

if (dl_saved_libname)
free(dl_saved_libname);
dl_saved_libname = xstrdup(libname_path);

return 1;
err:
fprintf(stderr,
"Cannot load AVAHI library (%s) : %s. AVAHI search disabled.\n",
libname_path, dl_error);
dl_handle = (void *)1;
lt_dlexit();
if (dl_saved_libname) {
free(dl_saved_libname);
dl_saved_libname = NULL;
}
return 0;
}
/* end of dynamic link library stuff */
Expand Down Expand Up @@ -600,4 +621,8 @@ nutscan_device_t * nutscan_scan_avahi(useconds_t usec_timeout)
return NULL;
}

int nutscan_unload_avahi_library(void)
{
return 0;
}
#endif /* WITH_AVAHI */
25 changes: 25 additions & 0 deletions tools/nut-scanner/scan_ipmi.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@
#include "nut-scan.h"
#include "nut_stdint.h"

/* externally visible to nutscan-init */
int nutscan_unload_ipmi_library(void);

#ifdef WITH_IPMI

#include "upsclient.h"
Expand All @@ -46,6 +49,7 @@
/* dynamic link library stuff */
static lt_dlhandle dl_handle = NULL;
static const char *dl_error = NULL;
static char *dl_saved_libname = NULL;

#ifdef HAVE_FREEIPMI_11X_12X
/* Functions symbols remapping */
Expand Down Expand Up @@ -134,6 +138,15 @@ typedef int bool_t;
static nutscan_device_t * nutscan_scan_ipmi_device(const char * IPaddr, nutscan_ipmi_t * sec);
static void * nutscan_scan_ipmi_device_thready(void * arg_sec);

/* return 0 on success, -1 on error e.g. "was not loaded";
* other values may be possible if lt_dlclose() errors set them;
* visible externally */
int nutscan_unload_library(int *avail, lt_dlhandle *pdl_handle, char **libpath);
int nutscan_unload_ipmi_library(void)
{
return nutscan_unload_library(&nutscan_avail_ipmi, &dl_handle, &dl_saved_libname);
}

/* Return 0 on error; visible externally */
int nutscan_load_ipmi_library(const char *libname_path);
int nutscan_load_ipmi_library(const char *libname_path)
Expand Down Expand Up @@ -261,6 +274,10 @@ int nutscan_load_ipmi_library(const char *libname_path)
goto err;
}

if (dl_saved_libname)
free(dl_saved_libname);
dl_saved_libname = xstrdup(libname_path);

return 1;

err:
Expand All @@ -269,6 +286,10 @@ int nutscan_load_ipmi_library(const char *libname_path)
libname_path, dl_error);
dl_handle = (void *)1;
lt_dlexit();
if (dl_saved_libname) {
free(dl_saved_libname);
dl_saved_libname = NULL;
}
return 0;
}
/* end of dynamic link library stuff */
Expand Down Expand Up @@ -1048,4 +1069,8 @@ nutscan_device_t * nutscan_scan_ip_range_ipmi(nutscan_ip_range_list_t * irl, nu
return NULL;
}

int nutscan_unload_ipmi_library(void)
{
return 0;
}
#endif /* WITH_IPMI */
19 changes: 19 additions & 0 deletions tools/nut-scanner/scan_nut.c
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
/* dynamic link library stuff */
static lt_dlhandle dl_handle = NULL;
static const char *dl_error = NULL;
static char *dl_saved_libname = NULL;

static int (*nut_upscli_splitaddr)(const char *buf, char **hostname, uint16_t *port);
static int (*nut_upscli_tryconnect)(UPSCONN_t *ups, const char *host, uint16_t port,
Expand Down Expand Up @@ -68,6 +69,16 @@ struct scan_nut_arg {
useconds_t timeout;
};

/* return 0 on success, -1 on error e.g. "was not loaded";
* other values may be possible if lt_dlclose() errors set them;
* visible externally */
int nutscan_unload_library(int *avail, lt_dlhandle *pdl_handle, char **libpath);
int nutscan_unload_upsclient_library(void);
int nutscan_unload_upsclient_library(void)
{
return nutscan_unload_library(&nutscan_avail_nut, &dl_handle, &dl_saved_libname);
}

/* return 0 on error; visible externally */
int nutscan_load_upsclient_library(const char *libname_path);
int nutscan_load_upsclient_library(const char *libname_path)
Expand Down Expand Up @@ -129,6 +140,10 @@ int nutscan_load_upsclient_library(const char *libname_path)
goto err;
}

if (dl_saved_libname)
free(dl_saved_libname);
dl_saved_libname = xstrdup(libname_path);

return 1;

err:
Expand All @@ -137,6 +152,10 @@ int nutscan_load_upsclient_library(const char *libname_path)
libname_path, dl_error);
dl_handle = (void *)1;
lt_dlexit();
if (dl_saved_libname) {
free(dl_saved_libname);
dl_saved_libname = NULL;
}
return 0;
}
/* end of dynamic link library stuff */
Expand Down
34 changes: 32 additions & 2 deletions tools/nut-scanner/scan_snmp.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,9 @@
#include "nut-scan.h"
#include "nut_stdint.h"

/* externally visible to nutscan-init */
int nutscan_unload_snmp_library(void);

#ifdef WITH_SNMP

#ifndef WIN32
Expand Down Expand Up @@ -116,6 +119,7 @@ typedef int bool_t;
/* dynamic link library stuff */
static lt_dlhandle dl_handle = NULL;
static const char *dl_error = NULL;
static char *dl_saved_libname = NULL;
#endif /* WITH_SNMP_STATIC */

static void (*nut_init_snmp)(const char *type);
Expand Down Expand Up @@ -177,9 +181,23 @@ static oid *nut_usmHMAC256SHA384AuthProtocol;
static oid *nut_usmHMAC384SHA512AuthProtocol;
#endif

/* return 0 on success, -1 on error e.g. "was not loaded";
* other values may be possible if lt_dlclose() errors set them;
* visible externally */
#ifndef WITH_SNMP_STATIC
int nutscan_unload_library(int *avail, lt_dlhandle *pdl_handle, char **libpath);
#endif
int nutscan_unload_snmp_library(void)
{
#ifdef WITH_SNMP_STATIC
return 0;
#else
return nutscan_unload_library(&nutscan_avail_snmp, &dl_handle, &dl_saved_libname);
#endif
}

/* return 0 on error; visible externally */
int nutscan_load_snmp_library(const char *libname_path);

int nutscan_load_snmp_library(const char *libname_path)
{
#ifdef WITH_SNMP_STATIC
Expand Down Expand Up @@ -453,7 +471,11 @@ int nutscan_load_snmp_library(const char *libname_path)
}
#endif /* NUT_HAVE_LIBNETSNMP_usmHMAC384SHA512AuthProtocol */

#endif /* WITH_SNMP_STATIC */
if (dl_saved_libname)
free(dl_saved_libname);
dl_saved_libname = xstrdup(libname_path);

#endif /* not WITH_SNMP_STATIC */

return 1;

Expand All @@ -464,6 +486,10 @@ int nutscan_load_snmp_library(const char *libname_path)
libname_path, dl_error);
dl_handle = (void *)1;
lt_dlexit();
if (dl_saved_libname) {
free(dl_saved_libname);
dl_saved_libname = NULL;
}
return 0;
#endif /* not WITH_SNMP_STATIC */
}
Expand Down Expand Up @@ -1422,4 +1448,8 @@ nutscan_device_t * nutscan_scan_ip_range_snmp(nutscan_ip_range_list_t * irl,
return NULL;
}

int nutscan_unload_snmp_library(void)
{
return 0;
}
#endif /* WITH_SNMP */
Loading

0 comments on commit f2e9229

Please sign in to comment.