Commit f3670470 authored by Rex's avatar Rex

MDEV-30815 Printing a stack trace leaks file descriptors.

	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.
parent 231c0eb7
...@@ -75,7 +75,8 @@ typedef struct { ...@@ -75,7 +75,8 @@ typedef struct {
#ifdef HAVE_MY_ADDR_RESOLVE #ifdef HAVE_MY_ADDR_RESOLVE
int my_addr_resolve(void *ptr, my_addr_loc *loc); 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 #else
#define my_addr_resolve_init() (0) #define my_addr_resolve_init() (0)
#define my_addr_resolve(A,B) (1) #define my_addr_resolve(A,B) (1)
......
...@@ -115,7 +115,7 @@ int my_addr_resolve(void *ptr, my_addr_loc *loc) ...@@ -115,7 +115,7 @@ int my_addr_resolve(void *ptr, my_addr_loc *loc)
return 1; return 1;
} }
const char *my_addr_resolve_init() const char *my_addr_resolve_init(void *ptr)
{ {
if (!bfdh) if (!bfdh)
{ {
...@@ -145,6 +145,11 @@ const char *my_addr_resolve_init() ...@@ -145,6 +145,11 @@ const char *my_addr_resolve_init()
err: err:
return bfd_errmsg(bfd_get_error()); return bfd_errmsg(bfd_get_error());
} }
void my_addr_resolve_close()
{
}
#elif defined(HAVE_LIBELF_H) #elif defined(HAVE_LIBELF_H)
/* /*
another possible implementation. another possible implementation.
...@@ -171,19 +176,11 @@ static char addr2line_binary[1024]; ...@@ -171,19 +176,11 @@ static char addr2line_binary[1024];
static char output[1024]; static char output[1024];
static struct pollfd poll_fds; static struct pollfd poll_fds;
static void *addr_offset; static void *addr_offset;
Dl_info info;
int start_addr2line_fork(const char *binary_path) 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) if (pipe(in) < 0)
return 1; return 1;
if (pipe(out) < 0) if (pipe(out) < 0)
...@@ -211,6 +208,16 @@ int start_addr2line_fork(const char *binary_path) ...@@ -211,6 +208,16 @@ int start_addr2line_fork(const char *binary_path)
return 0; 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 first_error= 0;
static int addr_resolve(void *ptr, my_addr_loc *loc) static int addr_resolve(void *ptr, my_addr_loc *loc)
...@@ -297,25 +304,40 @@ static int addr_resolve(void *ptr, my_addr_loc *loc) ...@@ -297,25 +304,40 @@ static int addr_resolve(void *ptr, my_addr_loc *loc)
int my_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)) 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 We use dli_fname in case the path is longer than the length of
our static string. We don't want to allocate anything our static string. We don't want to allocate anything
dynamically here as we are in a "crashed" state. 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); fputs("Can't start addr2line\n", stderr);
my_addr_resolve_close();
}
addr2line_binary[0] = '\0'; addr2line_binary[0] = '\0';
return 2; return "fork() error";
} }
/* Save result for future comparisons. */ /* Save result for future comparisons. */
strnmov(addr2line_binary, info.dli_fname, sizeof(addr2line_binary)); strnmov(addr2line_binary, info.dli_fname, sizeof(addr2line_binary));
...@@ -325,20 +347,7 @@ int my_addr_resolve(void *ptr, my_addr_loc *loc) ...@@ -325,20 +347,7 @@ int my_addr_resolve(void *ptr, my_addr_loc *loc)
done with PIE or not. done with PIE or not.
*/ */
addr_offset= (void*) info.dli_fbase; 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
}
return addr_resolve((void*) (ptr - addr_offset), loc);
}
const char *my_addr_resolve_init()
{
return 0; return 0;
} }
#endif #endif
...@@ -225,7 +225,7 @@ static void print_stack(void **frame) ...@@ -225,7 +225,7 @@ static void print_stack(void **frame)
const char *err; const char *err;
int i; 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); fprintf(stderr, "(my_addr_resolve failure: %s)\n", err);
return; return;
...@@ -243,6 +243,7 @@ static void print_stack(void **frame) ...@@ -243,6 +243,7 @@ static void print_stack(void **frame)
fprintf(stderr, "%s:%u", loc.file, loc.line); fprintf(stderr, "%s:%u", loc.file, loc.line);
} }
fprintf(stderr, "\n"); fprintf(stderr, "\n");
my_addr_resolve_close();
} }
#else #else
#define print_stack(X) fprintf(stderr, "???\n") #define print_stack(X) fprintf(stderr, "???\n")
......
...@@ -185,7 +185,7 @@ static int print_with_addr_resolve(void **addrs, int n) ...@@ -185,7 +185,7 @@ static int print_with_addr_resolve(void **addrs, int n)
int i; int i;
const char *err; 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); my_safe_printf_stderr("(my_addr_resolve failure: %s)\n", err);
return 0; return 0;
...@@ -200,6 +200,7 @@ static int print_with_addr_resolve(void **addrs, int n) ...@@ -200,6 +200,7 @@ static int print_with_addr_resolve(void **addrs, int n)
my_safe_printf_stderr("%s:%u(%s)[%p]\n", my_safe_printf_stderr("%s:%u(%s)[%p]\n",
loc.file, loc.line, loc.func, addrs[i]); loc.file, loc.line, loc.func, addrs[i]);
} }
my_addr_resolve_close();
return 1; return 1;
} }
#endif #endif
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment