diff options
Diffstat (limited to 'ext/mwrap/mwrap_core.h')
-rw-r--r-- | ext/mwrap/mwrap_core.h | 72 |
1 files changed, 55 insertions, 17 deletions
diff --git a/ext/mwrap/mwrap_core.h b/ext/mwrap/mwrap_core.h index 827ee7b..a84cd6d 100644 --- a/ext/mwrap/mwrap_core.h +++ b/ext/mwrap/mwrap_core.h @@ -4,7 +4,9 @@ * Disclaimer: I don't really know my way around XS or Perl internals well */ #define _LGPL_SOURCE /* allows URCU to inline some stuff */ -#define _GNU_SOURCE +#ifndef _GNU_SOURCE +# define _GNU_SOURCE +#endif #include "mymalloc.h" /* includes dlmalloc_c.h */ #ifndef MWRAP_PERL # define MWRAP_PERL 0 @@ -19,9 +21,6 @@ # define MWRAP_BT_MAX 32 #endif -#ifndef _GNU_SOURCE -# define _GNU_SOURCE -#endif #include <execinfo.h> #include <stdio.h> #include <stdlib.h> @@ -389,11 +388,8 @@ static const COP *mwp_curcop(void) static const char *mw_perl_src_file_cstr(unsigned *lineno) { const COP *cop = mwp_curcop(); - if (!cop) return NULL; - const char *fn = CopFILE(cop); - if (!fn) return NULL; - *lineno = CopLINE(cop); - return fn; + *lineno = cop ? CopLINE(cop) : 0; + return cop ? CopFILE(cop) : NULL; } # define SRC_FILE_CSTR(lineno) mw_perl_src_file_cstr(lineno) #endif /* MWRAP_PERL */ @@ -735,6 +731,7 @@ enomem: struct dump_arg { FILE *fp; size_t min; + bool dump_csv; }; char **bt_syms(void * const *addrlist, uint32_t size) @@ -745,7 +742,7 @@ char **bt_syms(void * const *addrlist, uint32_t size) #else /* make FreeBSD look like glibc output: */ char **s = backtrace_symbols_fmt(addrlist, size, "%f(%n%D) [%a]"); #endif - if (!s) fprintf(stderr, "backtrace_symbols: %m\n"); + if (!s) perror("backtrace_symbols"); return s; } @@ -757,12 +754,16 @@ static void cleanup_free(void *any) free(*p); } +static void *write_csv(FILE *, size_t min, const char *sort, size_t sort_len); static void *dump_to_file(struct dump_arg *a) { struct cds_lfht_iter iter; struct src_loc *l; struct cds_lfht *t; + if (a->dump_csv) + return write_csv(a->fp, a->min, NULL, 0); + ++locating; rcu_read_lock(); t = CMM_LOAD_SHARED(totals); @@ -860,7 +861,7 @@ __attribute__ ((destructor)) static void mwrap_dtor(void) { const char *opt = getenv("MWRAP"); const char *modes[] = { "a", "a+", "w", "w+", "r+" }; - struct dump_arg a = { .min = 0 }; + struct dump_arg a = { .min = 0, .dump_csv = false }; size_t i; int dump_fd; char *dump_path; @@ -873,27 +874,64 @@ __attribute__ ((destructor)) static void mwrap_dtor(void) return; ++locating; - if ((dump_path = strstr(opt, "dump_path:")) && - (dump_path += sizeof("dump_path")) && - *dump_path) { + + /* parse dump_csv:$PATHNAME */ + if ((dump_path = strstr(opt, "dump_csv:"))) { + dump_path += sizeof("dump_csv"); + if (!*dump_path) + dump_path = NULL; + else + a.dump_csv = true; + } + if (!dump_path) { + /* parse dump_path:$PATHNAME */ + if ((dump_path = strstr(opt, "dump_path:"))) { + dump_path += sizeof("dump_path"); + if (!*dump_path) + dump_path = NULL; + } + } + if (dump_path) { char *end = strchr(dump_path, ','); char buf[PATH_MAX]; + AUTO_FREE char *pid_path = NULL; if (end) { mwrap_assert((end - dump_path) < (intptr_t)sizeof(buf)); end = mempcpy(buf, dump_path, end - dump_path); *end = 0; dump_path = buf; } + + /* %p => PID expansion (Linux core_pattern uses %p, too) */ + if ((s = strchr(dump_path, '%')) && s[1] == 'p' && + /* don't allow injecting extra formats: */ + !strchr(s + 2, '%')) { + s[1] = 'd'; /* s/%p/%d/ to make asprintf happy */ + int n = asprintf(&pid_path, dump_path, (int)getpid()); + if (n < 0) + fprintf(stderr, + "asprintf failed: %m, dumping to %s\n", + dump_path); + else + dump_path = pid_path; + } dump_fd = open(dump_path, O_CLOEXEC|O_WRONLY|O_APPEND|O_CREAT, 0666); if (dump_fd < 0) { fprintf(stderr, "open %s failed: %m\n", dump_path); goto out; } + } else { + s = strstr(opt, "dump_fd:"); + if (!s) + goto out; + if (!sscanf(s, "dump_fd:%d", &dump_fd)) + goto out; } - else if (!sscanf(opt, "dump_fd:%d", &dump_fd)) - goto out; + /* allow dump_csv standalone for dump_fd */ + if (!a.dump_csv && strstr(opt, "dump_csv")) + a.dump_csv = true; if ((s = strstr(opt, "dump_min:"))) sscanf(s, "dump_min:%zu", &a.min); @@ -1019,7 +1057,7 @@ __attribute__((constructor)) static void mwrap_ctor(void) h->real = h; call_rcu(&h->as.dead, free_hdr_rcu); } else - fprintf(stderr, "malloc: %m\n"); + perror("malloc"); h1d_start(); CHECK(int, 0, pthread_sigmask(SIG_SETMASK, &old, NULL)); |