103 lines
3.1 KiB
Diff
103 lines
3.1 KiB
Diff
From 66a8a1421e4520e9dda0a46704e25bafb989b1ae Mon Sep 17 00:00:00 2001
|
|
From: "Andrew G. Morgan" <morgan@kernel.org>
|
|
Date: Sat, 5 Feb 2022 17:26:05 -0800
|
|
Subject: [PATCH] psx: free allocated memory at exit.
|
|
|
|
Kalen Hall reported that Valgrind detected a memory leak associated
|
|
with a multi-threaded program linked against libcap and libpsx.
|
|
|
|
https://bugzilla.kernel.org/show_bug.cgi?id=215551
|
|
|
|
I've been unable to validate this myself with valgrind (likely holding
|
|
it wrong), but did explore psx for allocated memory and via fprintf's
|
|
convinced myself that this change should pair all calloc()s with a
|
|
corresponding free().
|
|
|
|
Signed-off-by: Andrew G. Morgan <morgan@kernel.org>
|
|
---
|
|
psx/psx.c | 44 +++++++++++++++++++++++++++++++++++++++++++-
|
|
1 file changed, 43 insertions(+), 1 deletion(-)
|
|
|
|
diff --git a/psx/psx.c b/psx/psx.c
|
|
index 6b669ae..1876978 100644
|
|
--- a/psx/psx.c
|
|
+++ b/psx/psx.c
|
|
@@ -29,6 +29,26 @@
|
|
|
|
#include "psx_syscall.h"
|
|
|
|
+#ifdef _PSX_DEBUG_MEMORY
|
|
+
|
|
+static void *_psx_calloc(const char *file, const int line,
|
|
+ size_t nmemb, size_t size) {
|
|
+ void *ptr = calloc(nmemb, size);
|
|
+ fprintf(stderr, "psx:%d:%s:%d: calloc(%ld, %ld) -> %p\n", gettid(),
|
|
+ file, line, (long int)nmemb, (long int)size, ptr);
|
|
+ return ptr;
|
|
+}
|
|
+
|
|
+static void _psx_free(const char *file, const int line, void *ptr) {
|
|
+ fprintf(stderr, "psx:%d:%s:%d: free(%p)\n", gettid(), file, line, ptr);
|
|
+ return free(ptr);
|
|
+}
|
|
+
|
|
+#define calloc(a, b) _psx_calloc(__FILE__, __LINE__, a, b)
|
|
+#define free(a) _psx_free(__FILE__, __LINE__, a)
|
|
+
|
|
+#endif /* def _PSX_DEBUG_MEMORY */
|
|
+
|
|
/*
|
|
* psx_load_syscalls() can be weakly defined in dependent libraries to
|
|
* provide a mechanism for a library to optionally leverage this psx
|
|
@@ -177,6 +197,7 @@ static void psx_posix_syscall_actor(int signum, siginfo_t *info, void *ignore) {
|
|
* Some forward declarations for the initialization
|
|
* psx_syscall_start() routine.
|
|
*/
|
|
+static void _psx_cleanup(void);
|
|
static void _psx_prepare_fork(void);
|
|
static void _psx_fork_completed(void);
|
|
static void _psx_forked_child(void);
|
|
@@ -240,6 +261,7 @@ static void psx_syscall_start(void) {
|
|
|
|
psx_confirm_sigaction();
|
|
psx_do_registration(); /* register the main thread. */
|
|
+ atexit(_psx_cleanup);
|
|
|
|
psx_tracker.initialized = 1;
|
|
}
|
|
@@ -420,7 +442,7 @@ static void _psx_exiting(void *node) {
|
|
pthread_sigmask(SIG_SETMASK, &orig_sigbits, NULL);
|
|
|
|
/*
|
|
- * Allow the rest of the psx system carry on as per normal.
|
|
+ * Allow the rest of the psx system to carry on as per normal.
|
|
*/
|
|
psx_new_state(_PSX_EXITING, _PSX_IDLE);
|
|
}
|
|
@@ -699,2 +721,22 @@ defer:
|
|
return ret;
|
|
}
|
|
+/*
|
|
+ * _psx_cleanup its called when the program exits. It is used to free
|
|
+ * any memory used by the thread tracker.
|
|
+ */
|
|
+static void _psx_cleanup(void) {
|
|
+ registered_thread_t *ref, *next;
|
|
+
|
|
+ /*
|
|
+ * We enter the exiting state. Unlike exiting a single thread we
|
|
+ * never leave this state since this cleanup is only done at
|
|
+ * program exit.
|
|
+ */
|
|
+ psx_new_state(_PSX_IDLE, _PSX_EXITING);
|
|
+
|
|
+ for (ref = psx_tracker.root; ref; ref = next) {
|
|
+ next = ref->next;
|
|
+ psx_do_unregister(ref);
|
|
+ }
|
|
+}
|
|
+
|
|
--
|
|
2.27.0
|
|
|