summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRex <rex.johnston@mariadb.com>2023-03-09 13:41:07 +1200
committerRex <rex.johnston@mariadb.com>2023-03-09 14:52:22 +1200
commitf367047033f2096dbbee7f67f5931b9faf49d483 (patch)
tree1db2f1be7039a880cf03217cfc92f1e37697f98e
parent231c0eb7a68570da6b5b3741b2f1431c2f43c475 (diff)
downloadmariadb-git-bb-10.5-MDEV-30815.tar.gz
MDEV-30815 Printing a stack trace leaks file descriptors.bb-10.5-MDEV-30815
In situations where mariadbd emits a lot of stack traces it can run out of file descriptors. Each time the pipe to the external utility addr2line is opened, those file descriptor are never closed.
-rw-r--r--include/my_stacktrace.h3
-rw-r--r--mysys/my_addr_resolve.c95
-rw-r--r--mysys/safemalloc.c3
-rw-r--r--mysys/stacktrace.c3
4 files changed, 58 insertions, 46 deletions
diff --git a/include/my_stacktrace.h b/include/my_stacktrace.h
index 20b86f45232..924f198be3e 100644
--- a/include/my_stacktrace.h
+++ b/include/my_stacktrace.h
@@ -75,7 +75,8 @@ typedef struct {
#ifdef HAVE_MY_ADDR_RESOLVE
int my_addr_resolve(void *ptr, my_addr_loc *loc);
-const char *my_addr_resolve_init();
+const char *my_addr_resolve_init(void *ptr);
+void my_addr_resolve_close();
#else
#define my_addr_resolve_init() (0)
#define my_addr_resolve(A,B) (1)
diff --git a/mysys/my_addr_resolve.c b/mysys/my_addr_resolve.c
index 336e419806d..e4d3fd1fff6 100644
--- a/mysys/my_addr_resolve.c
+++ b/mysys/my_addr_resolve.c
@@ -115,7 +115,7 @@ int my_addr_resolve(void *ptr, my_addr_loc *loc)
return 1;
}
-const char *my_addr_resolve_init()
+const char *my_addr_resolve_init(void *ptr)
{
if (!bfdh)
{
@@ -145,6 +145,11 @@ const char *my_addr_resolve_init()
err:
return bfd_errmsg(bfd_get_error());
}
+
+
+void my_addr_resolve_close()
+{
+}
#elif defined(HAVE_LIBELF_H)
/*
another possible implementation.
@@ -171,19 +176,11 @@ static char addr2line_binary[1024];
static char output[1024];
static struct pollfd poll_fds;
static void *addr_offset;
+Dl_info info;
+
int start_addr2line_fork(const char *binary_path)
{
-
- if (pid > 0)
- {
- /* Don't leak FDs */
- close(in[1]);
- close(out[0]);
- /* Don't create zombie processes. */
- waitpid(pid, NULL, 0);
- }
-
if (pipe(in) < 0)
return 1;
if (pipe(out) < 0)
@@ -211,6 +208,16 @@ int start_addr2line_fork(const char *binary_path)
return 0;
}
+
+void my_addr_resolve_close()
+{
+ /* Don't leak FDs */
+ close(in[1]);
+ close(out[0]);
+ /* Don't create zombie processes. */
+ waitpid(pid, NULL, 0);
+}
+
static int first_error= 0;
static int addr_resolve(void *ptr, my_addr_loc *loc)
@@ -297,48 +304,50 @@ static int addr_resolve(void *ptr, my_addr_loc *loc)
int my_addr_resolve(void *ptr, my_addr_loc *loc)
{
- Dl_info info;
+#ifndef __PIE__
+ addr_offset= (void*) info.dli_fbase;
+ if (strcmp(info.dli_fname, my_progname) == 0 &&
+ addr_resolve((void*) my_addr_resolve, loc) == 0 &&
+ strcmp(loc->func, "my_addr_resolve") == 0)
+ addr_offset= 0;
+#endif
+ return addr_resolve((void*) (ptr - addr_offset), loc);
+}
+
+
+const char *my_addr_resolve_init(void *ptr)
+{
if (!dladdr(ptr, &info))
- return 1;
+ return "dladdr() error";
- if (strcmp(addr2line_binary, info.dli_fname))
- {
- /*
- We use dli_fname in case the path is longer than the length of
- our static string. We don't want to allocate anything
- dynamically here as we are in a "crashed" state.
+ /*
+ We use dli_fname in case the path is longer than the length of
+ our static string. We don't want to allocate anything
+ dynamically here as we are in a "crashed" state.
*/
- if (start_addr2line_fork(info.dli_fname))
+
+ if (start_addr2line_fork(info.dli_fname))
+ {
+ if (!first_error++)
{
- if (!first_error++)
- fputs("Can't start addr2line\n", stderr);
- addr2line_binary[0] = '\0';
- return 2;
+ fputs("Can't start addr2line\n", stderr);
+ my_addr_resolve_close();
}
- /* Save result for future comparisons. */
- strnmov(addr2line_binary, info.dli_fname, sizeof(addr2line_binary));
-
- /*
- Check if we should use info.dli_fbase as an offset or not
- for the base program. This is depending on if the compilation is
- done with PIE or not.
- */
- addr_offset= (void*) info.dli_fbase;
-#ifndef __PIE__
- if (strcmp(info.dli_fname, my_progname) == 0 &&
- addr_resolve((void*) my_addr_resolve, loc) == 0 &&
- strcmp(loc->func, "my_addr_resolve") == 0)
- addr_offset= 0;
-#endif
+ addr2line_binary[0] = '\0';
+ return "fork() error";
}
- return addr_resolve((void*) (ptr - addr_offset), loc);
-}
+ /* Save result for future comparisons. */
+ strnmov(addr2line_binary, info.dli_fname, sizeof(addr2line_binary));
+ /*
+ Check if we should use info.dli_fbase as an offset or not
+ for the base program. This is depending on if the compilation is
+ done with PIE or not.
+ */
+ addr_offset= (void*) info.dli_fbase;
-const char *my_addr_resolve_init()
-{
return 0;
}
#endif
diff --git a/mysys/safemalloc.c b/mysys/safemalloc.c
index 8ccc49bbb23..ba22d629dae 100644
--- a/mysys/safemalloc.c
+++ b/mysys/safemalloc.c
@@ -225,7 +225,7 @@ static void print_stack(void **frame)
const char *err;
int i;
- if ((err= my_addr_resolve_init()))
+ if ((err= my_addr_resolve_init(frame[0])))
{
fprintf(stderr, "(my_addr_resolve failure: %s)\n", err);
return;
@@ -243,6 +243,7 @@ static void print_stack(void **frame)
fprintf(stderr, "%s:%u", loc.file, loc.line);
}
fprintf(stderr, "\n");
+ my_addr_resolve_close();
}
#else
#define print_stack(X) fprintf(stderr, "???\n")
diff --git a/mysys/stacktrace.c b/mysys/stacktrace.c
index 5718b2e762d..6a9161460a0 100644
--- a/mysys/stacktrace.c
+++ b/mysys/stacktrace.c
@@ -185,7 +185,7 @@ static int print_with_addr_resolve(void **addrs, int n)
int i;
const char *err;
- if ((err= my_addr_resolve_init()))
+ if ((err= my_addr_resolve_init(addrs[0])))
{
my_safe_printf_stderr("(my_addr_resolve failure: %s)\n", err);
return 0;
@@ -200,6 +200,7 @@ static int print_with_addr_resolve(void **addrs, int n)
my_safe_printf_stderr("%s:%u(%s)[%p]\n",
loc.file, loc.line, loc.func, addrs[i]);
}
+ my_addr_resolve_close();
return 1;
}
#endif