summaryrefslogtreecommitdiff
path: root/select.c
diff options
context:
space:
mode:
authorNick Mathewson <nickm@torproject.org>2011-01-12 21:41:58 -0500
committerNick Mathewson <nickm@torproject.org>2011-01-12 21:41:58 -0500
commit8b0afe96eb3436bfa286a1fb2059f137458139b7 (patch)
treec825dac40f65a3c411ecb15dc9e0267f13458998 /select.c
parentb647e0bc94a6c1a32767f00b6c19a22483720c4f (diff)
parent0c0ec0be2ba977b8133294e27b076a65a2d65711 (diff)
downloadlibevent-8b0afe96eb3436bfa286a1fb2059f137458139b7.tar.gz
Merge remote branch 'origin/patches-2.0'
Diffstat (limited to 'select.c')
-rw-r--r--select.c36
1 files changed, 27 insertions, 9 deletions
diff --git a/select.c b/select.c
index 0ad04468..b2a37332 100644
--- a/select.c
+++ b/select.c
@@ -91,6 +91,7 @@ const struct eventop selectops = {
};
static int select_resize(struct selectop *sop, int fdsz);
+static void select_free_selectop(struct selectop *sop);
static void *
select_init(struct event_base *base)
@@ -100,7 +101,10 @@ select_init(struct event_base *base)
if (!(sop = mm_calloc(1, sizeof(struct selectop))))
return (NULL);
- select_resize(sop, howmany(32 + 1, NFDBITS)*sizeof(fd_mask));
+ if (select_resize(sop, howmany(32 + 1, NFDBITS)*sizeof(fd_mask))) {
+ select_free_selectop(sop);
+ return (NULL);
+ }
evsig_init(base);
@@ -129,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;
}
@@ -186,7 +193,6 @@ select_dispatch(struct event_base *base, struct timeval *tv)
return (0);
}
-
static int
select_resize(struct selectop *sop, int fdsz)
{
@@ -199,8 +205,15 @@ select_resize(struct selectop *sop, int fdsz)
if ((readset_in = mm_realloc(sop->event_readset_in, fdsz)) == NULL)
goto error;
sop->event_readset_in = readset_in;
- if ((writeset_in = mm_realloc(sop->event_writeset_in, fdsz)) == NULL)
+ if ((writeset_in = mm_realloc(sop->event_writeset_in, fdsz)) == NULL) {
+ /* 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;
sop->resize_out_sets = 1;
@@ -293,11 +306,8 @@ select_del(struct event_base *base, int fd, short old, short events, void *p)
}
static void
-select_dealloc(struct event_base *base)
+select_free_selectop(struct selectop *sop)
{
- struct selectop *sop = base->evbase;
-
- evsig_dealloc(base);
if (sop->event_readset_in)
mm_free(sop->event_readset_in);
if (sop->event_writeset_in)
@@ -310,3 +320,11 @@ select_dealloc(struct event_base *base)
memset(sop, 0, sizeof(struct selectop));
mm_free(sop);
}
+
+static void
+select_dealloc(struct event_base *base)
+{
+ evsig_dealloc(base);
+
+ select_free_selectop(base->evbase);
+}