]> granicus.if.org Git - libevent/commitdiff
Handle resize failures in the select backend better.
authorNick Mathewson <nickm@torproject.org>
Fri, 7 Jan 2011 18:18:09 +0000 (13:18 -0500)
committerNick Mathewson <nickm@torproject.org>
Fri, 7 Jan 2011 18:18:09 +0000 (13:18 -0500)
select.c

index 993a4e603008f9fa8356be454e4459adb6727903..8327518eb4da4b1137a4d19c767e7495929d43c7 100644 (file)
--- a/select.c
+++ b/select.c
@@ -100,7 +100,9 @@ select_init(struct event_base *base)
                return (NULL);
 
        if (select_resize(sop, howmany(32 + 1, NFDBITS)*sizeof(fd_mask))) {
-               mm_free(sop);
+               /* select_resize might have left this around. */
+               if (sop->event_readset_in)
+                       mm_free(sop->event_readset_in);
                return (NULL);
        }
 
@@ -131,11 +133,14 @@ select_dispatch(struct event_base *base, struct timeval *tv)
                size_t sz = sop->event_fdsz;
                if (!(readset_out = mm_realloc(sop->event_readset_out, sz)))
                        return (-1);
+               sop->event_readset_out = readset_out;
                if (!(writeset_out = mm_realloc(sop->event_writeset_out, sz))) {
-                       mm_free(readset_out);
+                       /* We don't free readset_out here, since it was
+                        * already successfully reallocated. The next time
+                        * we call select_dispatch, the realloc will be a
+                        * no-op. */
                        return (-1);
                }
-               sop->event_readset_out = readset_out;
                sop->event_writeset_out = writeset_out;
                sop->resize_out_sets = 0;
        }
@@ -188,7 +193,6 @@ select_dispatch(struct event_base *base, struct timeval *tv)
        return (0);
 }
 
-
 static int
 select_resize(struct selectop *sop, int fdsz)
 {
@@ -202,7 +206,12 @@ select_resize(struct selectop *sop, int fdsz)
                goto error;
        sop->event_readset_in = readset_in;
        if ((writeset_in = mm_realloc(sop->event_writeset_in, fdsz)) == NULL) {
-               mm_free(readset_in);
+               /* Note that this will leave event_readset_in expanded.
+                * That's okay; we wouldn't want to free it, since that would
+                * change the semantics of select_resize from "expand the
+                * readset_in and writeset_in, or return -1" to "expand the
+                * *set_in members, or trash them and return -1."
+                */
                goto error;
        }
        sop->event_writeset_in = writeset_in;