From 4547a1c29960f9ec7c5f2d2a5f8c204da70a116b Mon Sep 17 00:00:00 2001 From: Eric Wong Date: Thu, 15 Dec 2022 20:52:38 +0000 Subject: introduce AUTO_FREE macro to simplify cleanup Both gcc and clang have had __attribute__((__cleanup__)) for a decade or more. This helps us avoid memory leaks and simplifies our code. --- Mwrap.xs | 3 +-- mwrap_core.h | 14 ++++++++++---- mwrap_httpd.h | 18 +++++------------- 3 files changed, 16 insertions(+), 19 deletions(-) diff --git a/Mwrap.xs b/Mwrap.xs index 6adf975..9ebc082 100644 --- a/Mwrap.xs +++ b/Mwrap.xs @@ -25,7 +25,7 @@ static SV *location_string(struct src_loc *l) sv_catpvf(ret, ":%zu", l->lineno); } if (l->bt_len) { - char **s = bt_syms(l->bt, l->bt_len); + AUTO_FREE char **s = bt_syms(l->bt, l->bt_len); if (s) { if (l->f) sv_catpvs(ret, "\n"); @@ -33,7 +33,6 @@ static SV *location_string(struct src_loc *l) for (uint32_t i = 1; i < l->bt_len; ++i) sv_catpvf(ret, "\n%s", s[i]); } - free(s); } return ret; } diff --git a/mwrap_core.h b/mwrap_core.h index ec08ee1..2ef550a 100644 --- a/mwrap_core.h +++ b/mwrap_core.h @@ -714,6 +714,14 @@ char **bt_syms(void * const *addrlist, uint32_t size) return s; } +/* supported by modern gcc + clang */ +#define AUTO_FREE __attribute__((__cleanup__(cleanup_free))) +static void cleanup_free(void *any) +{ + void **p = any; + free(*p); +} + static void *dump_to_file(struct dump_arg *a) { struct cds_lfht_iter iter; @@ -730,13 +738,11 @@ static void *dump_to_file(struct dump_arg *a) if (l->total <= a->min) continue; if (loc_is_addr(l)) { - char **s = bt_syms(l->bt, 1); + AUTO_FREE char **s = bt_syms(l->bt, 1); - if (s) { + if (s) fprintf(a->fp, "%16zu %12zu %s\n", l->total, l->allocations, s[0]); - free(s); - } } else { fprintf(a->fp, "%16zu %12zu %s:%zu\n", l->total, l->allocations, l->f->fn, l->lineno); diff --git a/mwrap_httpd.h b/mwrap_httpd.h index aa4574a..1f706ea 100644 --- a/mwrap_httpd.h +++ b/mwrap_httpd.h @@ -420,7 +420,7 @@ static off_t write_loc_name(FILE *fp, const struct src_loc *l) fprintf(fp, ":%zu", l->lineno); } if (l->bt_len) { - char **s = bt_syms(l->bt, l->bt_len); + AUTO_FREE char **s = bt_syms(l->bt, l->bt_len); if (!s) return -1; if (l->f) fputc('\n', fp); @@ -436,7 +436,6 @@ static off_t write_loc_name(FILE *fp, const struct src_loc *l) fputc('\n', fp); fputs(s[i], fp); } - free(s); } off_t end = ftello(fp); if (end < 0) { @@ -560,14 +559,12 @@ static enum mw_qev each_gt(struct mw_h1 *h1, struct mw_h1req *h1r, struct mw_membuf ln; FILE *lp = memstream_new(&ln); if (!lp) return h1_close(h1); - struct h1_src_loc *hslv = accumulate(min, &hslc, lp); + AUTO_FREE struct h1_src_loc *hslv = accumulate(min, &hslc, lp); if (!hslv) return h1_close(h1); - if (err_close(lp)) { - free(hslv); + if (err_close(lp)) return h1_close(h1); - } char *n = ln.ptr; for (size_t i = 0; i < hslc; ++i) { @@ -575,7 +572,6 @@ static enum mw_qev each_gt(struct mw_h1 *h1, struct mw_h1req *h1r, n += hslv[i].lname_len; if (hslv[i].lname_len < 0) { free(ln.ptr); - free(hslv); return h1_close(h1); } } @@ -628,7 +624,6 @@ static enum mw_qev each_gt(struct mw_h1 *h1, struct mw_h1req *h1r, write_html(fp, hsl->loc_name, hsl->lname_len); FPUTS("", fp); } - free(hslv); free(ln.ptr); FPUTS("", fp); return h1_200(h1, fp, &mb); @@ -1041,7 +1036,6 @@ static void *h1d_run(void *x) /* pthread_create cb */ { struct mw_h1d *h1d = x; nfds_t i, nfds; - struct pollfd *pfd; int rc; struct mw_h1 *h1, *nxt; enum mw_qev ev; @@ -1053,7 +1047,7 @@ static void *h1d_run(void *x) /* pthread_create cb */ cds_list_for_each_entry_safe(h1, nxt, &h1d->conn, nd) if (poll_add(h1d, h1->fd, h1->events)) h1_close(h1); - pfd = poll_detach(h1d, &nfds); + AUTO_FREE struct pollfd *pfd = poll_detach(h1d, &nfds); rc = pfd ? poll(pfd, nfds, -1) : -1; if (rc < 0) { @@ -1083,10 +1077,8 @@ static void *h1d_run(void *x) /* pthread_create cb */ } } } - free(pfd); } - pfd = poll_detach(h1d, &nfds); - free(pfd); + free(poll_detach(h1d, &nfds)); cds_list_for_each_entry_safe(h1, nxt, &h1d->conn, nd) h1_close(h1); return NULL; -- cgit v1.2.3-24-ge0c7