about summary refs log tree commit homepage
diff options
context:
space:
mode:
authorEric Wong <e@80x24.org>2022-12-15 20:52:38 +0000
committerEric Wong <mwrap-perl@80x24.org>2022-12-16 09:27:38 +0000
commit4547a1c29960f9ec7c5f2d2a5f8c204da70a116b (patch)
tree03b8baff4d8e82b9a4b61e17d4ac68a5a5dc2d0d
parent956b57fbea889b9838f80f6f62df942bb5a8a76f (diff)
downloadmwrap-4547a1c29960f9ec7c5f2d2a5f8c204da70a116b.tar.gz
Both gcc and clang have had __attribute__((__cleanup__)) for a
decade or more.  This helps us avoid memory leaks and simplifies
our code.
-rw-r--r--Mwrap.xs3
-rw-r--r--mwrap_core.h14
-rw-r--r--mwrap_httpd.h18
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("</a></td></tr>", fp);
         }
-        free(hslv);
         free(ln.ptr);
         FPUTS("</table></body></html>", 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;