summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNick Mathewson <nickm@torproject.org>2010-01-22 16:14:49 -0500
committerNick Mathewson <nickm@torproject.org>2010-01-22 16:14:49 -0500
commitff3f6cd42b8d58d6db9c2ceb2cf9868d1a8f7ec0 (patch)
tree4fb607e14f39043f1f8a0d05c99a3d4e37bae1a3
parent7296971b105ffc2bc9d20b0a24a3055c2ecf5e69 (diff)
downloadlibevent-ff3f6cd42b8d58d6db9c2ceb2cf9868d1a8f7ec0.tar.gz
Check more internal event_add() calls for failure
Most of these should be unable to fail, since adding a timeout generally always works. Still, it's better not to try to be "too smart for our own good here." There are some remaining event_add() calls that I didn't add checks for; I've marked those with "XXXX" comments.
-rw-r--r--bufferevent-internal.h6
-rw-r--r--bufferevent.c31
-rw-r--r--bufferevent_async.c3
-rw-r--r--bufferevent_openssl.c140
-rw-r--r--bufferevent_pair.c6
-rw-r--r--bufferevent_ratelim.c20
-rw-r--r--bufferevent_sock.c13
-rw-r--r--evdns.c6
-rw-r--r--http.c7
-rw-r--r--include/event2/bufferevent.h2
10 files changed, 145 insertions, 89 deletions
diff --git a/bufferevent-internal.h b/bufferevent-internal.h
index 9594784a..eca52e77 100644
--- a/bufferevent-internal.h
+++ b/bufferevent-internal.h
@@ -219,7 +219,7 @@ struct bufferevent_ops {
void (*destruct)(struct bufferevent *);
/** Called when the timeouts on the bufferevent have changed.*/
- void (*adj_timeouts)(struct bufferevent *);
+ int (*adj_timeouts)(struct bufferevent *);
/** Called to flush data. */
int (*flush)(struct bufferevent *, short, enum bufferevent_flush_mode);
@@ -304,12 +304,12 @@ int _bufferevent_add_event(struct event *ev, const struct timeval *tv);
void _bufferevent_init_generic_timeout_cbs(struct bufferevent *bev);
/** Internal use: Delete the ev_read and ev_write callbacks if they're pending.
* Call this from the destructor function. */
-void _bufferevent_del_generic_timeout_cbs(struct bufferevent *bev);
+int _bufferevent_del_generic_timeout_cbs(struct bufferevent *bev);
/** Internal use: Add or delete the generic timeout events as appropriate.
* (If an event is enabled and a timeout is set, we add the event. Otherwise
* we delete it.) Call this from anything that changes the timeout values,
* that enabled EV_READ or EV_WRITE, or that disables EV_READ or EV_WRITE. */
-void _bufferevent_generic_adj_timeouts(struct bufferevent *bev);
+int _bufferevent_generic_adj_timeouts(struct bufferevent *bev);
/** Internal use: We have just successfully read data into an inbuf, so
* reset the read timeout (if any). */
diff --git a/bufferevent.c b/bufferevent.c
index 6e6c4187..77f18240 100644
--- a/bufferevent.c
+++ b/bufferevent.c
@@ -370,11 +370,12 @@ bufferevent_enable(struct bufferevent *bufev, short event)
return r;
}
-void
+int
bufferevent_set_timeouts(struct bufferevent *bufev,
const struct timeval *tv_read,
const struct timeval *tv_write)
{
+ int r = 0;
BEV_LOCK(bufev);
if (tv_read) {
bufev->timeout_read = *tv_read;
@@ -388,8 +389,10 @@ bufferevent_set_timeouts(struct bufferevent *bufev,
}
if (bufev->be_ops->adj_timeouts)
- bufev->be_ops->adj_timeouts(bufev);
+ r = bufev->be_ops->adj_timeouts(bufev);
BEV_UNLOCK(bufev);
+
+ return r;
}
@@ -687,26 +690,34 @@ _bufferevent_init_generic_timeout_cbs(struct bufferevent *bev)
bufferevent_generic_write_timeout_cb, bev);
}
-void
+int
_bufferevent_del_generic_timeout_cbs(struct bufferevent *bev)
{
- event_del(&bev->ev_read);
- event_del(&bev->ev_write);
+ int r1,r2;
+ r1 = event_del(&bev->ev_read);
+ r2 = event_del(&bev->ev_write);
+ if (r2<0 || r2<0)
+ return -1;
+ return 0;
}
-void
+int
_bufferevent_generic_adj_timeouts(struct bufferevent *bev)
{
const short enabled = bev->enabled;
+ int r1=0, r2=0;
if ((enabled & EV_READ) && evutil_timerisset(&bev->timeout_read))
- event_add(&bev->ev_read, &bev->timeout_read);
+ r1 = event_add(&bev->ev_read, &bev->timeout_read);
else
- event_del(&bev->ev_read);
+ r1 = event_del(&bev->ev_read);
if ((enabled & EV_WRITE) && evutil_timerisset(&bev->timeout_write))
- event_add(&bev->ev_write, &bev->timeout_write);
+ r2 = event_add(&bev->ev_write, &bev->timeout_write);
else
- event_del(&bev->ev_write);
+ r2 = event_del(&bev->ev_write);
+ if (r1 < 0 || r2 < 0)
+ return -1;
+ return 0;
}
int
diff --git a/bufferevent_async.c b/bufferevent_async.c
index 3d21d4c1..085a2db8 100644
--- a/bufferevent_async.c
+++ b/bufferevent_async.c
@@ -242,7 +242,8 @@ be_async_enable(struct bufferevent *buf, short what)
return -1;
/* NOTE: This interferes with non-blocking connect */
- _bufferevent_generic_adj_timeouts(buf);
+ if (_bufferevent_generic_adj_timeouts(buf) < 0)
+ return -1;
/* If we newly enable reading or writing, and we aren't reading or
writing already, consider launching a new read or write. */
diff --git a/bufferevent_openssl.c b/bufferevent_openssl.c
index 26be4ff1..3a239a44 100644
--- a/bufferevent_openssl.c
+++ b/bufferevent_openssl.c
@@ -317,7 +317,7 @@ struct bufferevent_openssl {
static int be_openssl_enable(struct bufferevent *, short);
static int be_openssl_disable(struct bufferevent *, short);
static void be_openssl_destruct(struct bufferevent *);
-static void be_openssl_adj_timeouts(struct bufferevent *);
+static int be_openssl_adj_timeouts(struct bufferevent *);
static int be_openssl_flush(struct bufferevent *bufev,
short iotype, enum bufferevent_flush_mode mode);
static int be_openssl_ctrl(struct bufferevent *, enum bufferevent_ctrl_op, union bufferevent_ctrl_data *);
@@ -363,41 +363,45 @@ put_error(struct bufferevent_openssl *bev_ssl, unsigned long err)
/* Have the base communications channel (either the underlying bufferevent or
* ev_read and ev_write) start reading. Take the read-blocked-on-write flag
* into account. */
-static void
+static int
start_reading(struct bufferevent_openssl *bev_ssl)
{
if (bev_ssl->underlying) {
short e = EV_READ;
if (bev_ssl->read_blocked_on_write)
e |= EV_WRITE;
- bufferevent_enable(bev_ssl->underlying, e);
+ return bufferevent_enable(bev_ssl->underlying, e);
} else {
struct bufferevent *bev = &bev_ssl->bev.bev;
- _bufferevent_add_event(&bev->ev_read, &bev->timeout_read);
- if (bev_ssl->read_blocked_on_write)
- _bufferevent_add_event(&bev->ev_write,
+ int r;
+ r = _bufferevent_add_event(&bev->ev_read, &bev->timeout_read);
+ if (r == 0 && bev_ssl->read_blocked_on_write)
+ r = _bufferevent_add_event(&bev->ev_write,
&bev->timeout_write);
+ return r;
}
}
/* Have the base communications channel (either the underlying bufferevent or
* ev_read and ev_write) start writing. Take the write-blocked-on-read flag
* into account. */
-static void
+static int
start_writing(struct bufferevent_openssl *bev_ssl)
{
+ int r;
if (bev_ssl->underlying) {
short e = EV_WRITE;
if (bev_ssl->write_blocked_on_read)
e |= EV_READ;
- bufferevent_enable(bev_ssl->underlying, e);
+ r = bufferevent_enable(bev_ssl->underlying, e);
} else {
struct bufferevent *bev = &bev_ssl->bev.bev;
- _bufferevent_add_event(&bev->ev_write, &bev->timeout_write);
- if (bev_ssl->write_blocked_on_read)
- _bufferevent_add_event(&bev->ev_read,
+ r = _bufferevent_add_event(&bev->ev_write, &bev->timeout_write);
+ if (!r && bev_ssl->write_blocked_on_read)
+ r = _bufferevent_add_event(&bev->ev_read,
&bev->timeout_read);
}
+ return r;
}
static void
@@ -426,45 +430,49 @@ stop_writing(struct bufferevent_openssl *bev_ssl)
}
}
-static void
+static int
set_rbow(struct bufferevent_openssl *bev_ssl)
{
if (!bev_ssl->underlying)
stop_reading(bev_ssl);
bev_ssl->read_blocked_on_write = 1;
- start_writing(bev_ssl);
+ return start_writing(bev_ssl);
}
-static void
+static int
set_wbor(struct bufferevent_openssl *bev_ssl)
{
if (!bev_ssl->underlying)
stop_writing(bev_ssl);
bev_ssl->write_blocked_on_read = 1;
- start_reading(bev_ssl);
+ return start_reading(bev_ssl);
}
-static void
+static int
clear_rbow(struct bufferevent_openssl *bev_ssl)
{
struct bufferevent *bev = &bev_ssl->bev.bev;
+ int r = 0;
bev_ssl->read_blocked_on_write = 0;
if (!(bev->enabled & EV_WRITE))
stop_writing(bev_ssl);
if (bev->enabled & EV_READ)
- start_reading(bev_ssl);
+ r = start_reading(bev_ssl);
+ return r;
}
-static void
+static int
clear_wbor(struct bufferevent_openssl *bev_ssl)
{
struct bufferevent *bev = &bev_ssl->bev.bev;
+ int r = 0;
bev_ssl->write_blocked_on_read = 0;
if (!(bev->enabled & EV_READ))
stop_reading(bev_ssl);
if (bev->enabled & EV_WRITE)
- start_writing(bev_ssl);
+ r = start_writing(bev_ssl);
+ return r;
}
static void
@@ -541,7 +549,8 @@ do_read(struct bufferevent_openssl *bev_ssl, int n_to_read)
r = SSL_read(bev_ssl->ssl, space[i].iov_base, space[i].iov_len);
if (r>0) {
if (bev_ssl->read_blocked_on_write)
- clear_rbow(bev_ssl);
+ if (clear_rbow(bev_ssl) < 0)
+ return -1;
++n_used;
space[i].iov_len = r;
/* Not exactly right; we probably want to do
@@ -554,13 +563,15 @@ do_read(struct bufferevent_openssl *bev_ssl, int n_to_read)
case SSL_ERROR_WANT_READ:
/* Can't read until underlying has more data. */
if (bev_ssl->read_blocked_on_write)
- clear_rbow(bev_ssl);
+ if (clear_rbow(bev_ssl) < 0)
+ return -1;
break;
case SSL_ERROR_WANT_WRITE:
/* This read operation requires a write, and the
* underlying is full */
if (!bev_ssl->read_blocked_on_write)
- set_rbow(bev_ssl);
+ if (set_rbow(bev_ssl) < 0)
+ return -1;
break;
default:
conn_closed(bev_ssl, err, r);
@@ -610,7 +621,8 @@ do_write(struct bufferevent_openssl *bev_ssl, int atmost)
space[i].iov_len);
if (r > 0) {
if (bev_ssl->write_blocked_on_read)
- clear_wbor(bev_ssl);
+ if (clear_wbor(bev_ssl) < 0)
+ return -1;
n_written += r;
bev_ssl->last_write = -1;
/* Not exactly right; we probably want to do
@@ -623,14 +635,16 @@ do_write(struct bufferevent_openssl *bev_ssl, int atmost)
case SSL_ERROR_WANT_WRITE:
/* Can't read until underlying has more data. */
if (bev_ssl->write_blocked_on_read)
- clear_wbor(bev_ssl);
+ if (clear_wbor(bev_ssl) < 0)
+ return -1;
bev_ssl->last_write = space[i].iov_len;
break;
case SSL_ERROR_WANT_READ:
/* This read operation requires a write, and the
* underlying is full */
if (!bev_ssl->write_blocked_on_read)
- set_wbor(bev_ssl);
+ if (set_wbor(bev_ssl) < 0)
+ return -1;
bev_ssl->last_write = space[i].iov_len;
break;
default:
@@ -786,16 +800,17 @@ be_openssl_writeeventcb(evutil_socket_t fd, short what, void *ptr)
_bufferevent_decref_and_unlock(&bev_ssl->bev.bev);
}
-static void
+static int
set_open_callbacks(struct bufferevent_openssl *bev_ssl, evutil_socket_t fd)
{
if (bev_ssl->underlying) {
bufferevent_setcb(bev_ssl->underlying,
be_openssl_readcb, be_openssl_writecb, be_openssl_eventcb,
bev_ssl);
+ return 0;
} else {
struct bufferevent *bev = &bev_ssl->bev.bev;
- int rpending=0, wpending=0;
+ int rpending=0, wpending=0, r1=0, r2=0;
if (fd < 0 && bev_ssl->fd_is_set)
fd = event_get_fd(&bev->ev_read);
if (bev_ssl->fd_is_set) {
@@ -809,12 +824,13 @@ set_open_callbacks(struct bufferevent_openssl *bev_ssl, evutil_socket_t fd)
event_assign(&bev->ev_write, bev->ev_base, fd,
EV_WRITE|EV_PERSIST, be_openssl_writeeventcb, bev_ssl);
if (rpending)
- _bufferevent_add_event(&bev->ev_read, &bev->timeout_read);
+ r1 = _bufferevent_add_event(&bev->ev_read, &bev->timeout_read);
if (wpending)
- _bufferevent_add_event(&bev->ev_write, &bev->timeout_write);
+ r2 = _bufferevent_add_event(&bev->ev_write, &bev->timeout_write);
if (fd >= 0) {
bev_ssl->fd_is_set = 1;
}
+ return (r1<0 || r2<0) ? -1 : 0;
}
}
@@ -837,7 +853,7 @@ do_handshake(struct bufferevent_openssl *bev_ssl)
if (r==1) {
/* We're done! */
bev_ssl->state = BUFFEREVENT_SSL_OPEN;
- set_open_callbacks(bev_ssl, -1);
+ set_open_callbacks(bev_ssl, -1); /* XXXX handle failure */
/* Call do_read and do_write as needed */
bufferevent_enable(&bev_ssl->bev.bev, bev_ssl->bev.bev.enabled);
_bufferevent_run_eventcb(&bev_ssl->bev.bev,
@@ -850,13 +866,13 @@ do_handshake(struct bufferevent_openssl *bev_ssl)
case SSL_ERROR_WANT_WRITE:
if (!bev_ssl->underlying) {
stop_reading(bev_ssl);
- start_writing(bev_ssl);
+ return start_writing(bev_ssl);
}
return 0;
case SSL_ERROR_WANT_READ:
if (!bev_ssl->underlying) {
stop_writing(bev_ssl);
- start_reading(bev_ssl);
+ return start_reading(bev_ssl);
}
return 0;
default:
@@ -870,7 +886,7 @@ static void
be_openssl_handshakecb(struct bufferevent *bev_base, void *ctx)
{
struct bufferevent_openssl *bev_ssl = ctx;
- do_handshake(bev_ssl);
+ do_handshake(bev_ssl);/* XXX handle failure */
}
static void
@@ -882,11 +898,11 @@ be_openssl_handshakeeventcb(evutil_socket_t fd, short what, void *ptr)
if (what & EV_TIMEOUT) {
_bufferevent_run_eventcb(&bev_ssl->bev.bev, BEV_EVENT_TIMEOUT);
} else
- do_handshake(bev_ssl);
+ do_handshake(bev_ssl);/* XXX handle failure */
_bufferevent_decref_and_unlock(&bev_ssl->bev.bev);
}
-static void
+static int
set_handshake_callbacks(struct bufferevent_openssl *bev_ssl, evutil_socket_t fd)
{
if (bev_ssl->underlying) {
@@ -894,9 +910,10 @@ set_handshake_callbacks(struct bufferevent_openssl *bev_ssl, evutil_socket_t fd)
be_openssl_handshakecb, be_openssl_handshakecb,
be_openssl_eventcb,
bev_ssl);
- do_handshake(bev_ssl);
+ return do_handshake(bev_ssl);
} else {
struct bufferevent *bev = &bev_ssl->bev.bev;
+ int r1=0, r2=0;
if (fd < 0 && bev_ssl->fd_is_set)
fd = event_get_fd(&bev->ev_read);
if (bev_ssl->fd_is_set) {
@@ -908,10 +925,11 @@ set_handshake_callbacks(struct bufferevent_openssl *bev_ssl, evutil_socket_t fd)
event_assign(&bev->ev_write, bev->ev_base, fd,
EV_WRITE|EV_PERSIST, be_openssl_handshakeeventcb, bev_ssl);
if (fd >= 0) {
- _bufferevent_add_event(&bev->ev_read, &bev->timeout_read);
- _bufferevent_add_event(&bev->ev_write, &bev->timeout_write);
+ r1 = _bufferevent_add_event(&bev->ev_read, &bev->timeout_read);
+ r2 = _bufferevent_add_event(&bev->ev_write, &bev->timeout_write);
bev_ssl->fd_is_set = 1;
}
+ return (r1<0 || r2<0) ? -1 : 0;
}
}
@@ -924,9 +942,10 @@ bufferevent_ssl_renegotiate(struct bufferevent *bev)
if (SSL_renegotiate(bev_ssl->ssl) < 0)
return -1;
bev_ssl->state = BUFFEREVENT_SSL_CONNECTING;
- set_handshake_callbacks(bev_ssl, -1);
+ if (set_handshake_callbacks(bev_ssl, -1) < 0)
+ return -1;
if (!bev_ssl->underlying)
- do_handshake(bev_ssl);
+ return do_handshake(bev_ssl);
return 0;
}
@@ -935,14 +954,16 @@ be_openssl_outbuf_cb(struct evbuffer *buf,
const struct evbuffer_cb_info *cbinfo, void *arg)
{
struct bufferevent_openssl *bev_ssl = arg;
+ int r = 0;
/* XXX need to hold a reference here. */
if (cbinfo->n_added && bev_ssl->state == BUFFEREVENT_SSL_OPEN) {
if (cbinfo->orig_size == 0)
- _bufferevent_add_event(&bev_ssl->bev.bev.ev_write,
+ r = _bufferevent_add_event(&bev_ssl->bev.bev.ev_write,
&bev_ssl->bev.bev.timeout_write);
consider_writing(bev_ssl);
}
+ /* XXX Handle r < 0 */
}
@@ -950,14 +971,15 @@ static int
be_openssl_enable(struct bufferevent *bev, short events)
{
struct bufferevent_openssl *bev_ssl = upcast(bev);
+ int r1 = 0, r2 = 0;
if (bev_ssl->state != BUFFEREVENT_SSL_OPEN)
return 0;
if (events & EV_READ)
- start_reading(bev_ssl);
+ r1 = start_reading(bev_ssl);
if (events & EV_WRITE)
- start_writing(bev_ssl);
+ r2 = start_writing(bev_ssl);
if (bev_ssl->underlying) {
_bufferevent_generic_adj_timeouts(bev);
@@ -967,7 +989,7 @@ be_openssl_enable(struct bufferevent *bev, short events)
if (events & EV_WRITE)
consider_writing(bev_ssl);
}
- return 0;
+ return (r1 < 0 || r2 < 0) ? -1 : 0;
}
static int
@@ -1008,18 +1030,20 @@ be_openssl_destruct(struct bufferevent *bev)
}
}
-static void
+static int
be_openssl_adj_timeouts(struct bufferevent *bev)
{
struct bufferevent_openssl *bev_ssl = upcast(bev);
if (bev_ssl->underlying)
- _bufferevent_generic_adj_timeouts(bev);
+ return _bufferevent_generic_adj_timeouts(bev);
else {
+ int r1=0, r2=0;
if (event_pending(&bev->ev_read, EV_READ, NULL))
- _bufferevent_add_event(&bev->ev_read, &bev->timeout_read);
+ r1 = _bufferevent_add_event(&bev->ev_read, &bev->timeout_read);
if (event_pending(&bev->ev_write, EV_WRITE, NULL))
- _bufferevent_add_event(&bev->ev_write, &bev->timeout_write);
+ r2 = _bufferevent_add_event(&bev->ev_write, &bev->timeout_write);
+ return (r1<0 || r2<0) ? -1 : 0;
}
}
@@ -1050,11 +1074,10 @@ be_openssl_ctrl(struct bufferevent *bev,
bev_ssl->fd_is_set = 1;
}
if (bev_ssl->state == BUFFEREVENT_SSL_OPEN)
- set_open_callbacks(bev_ssl, data->fd);
+ return set_open_callbacks(bev_ssl, data->fd);
else {
- set_handshake_callbacks(bev_ssl, data->fd);
+ return set_handshake_callbacks(bev_ssl, data->fd);
}
- return 0;
case BEV_CTRL_GET_FD:
if (bev_ssl->underlying)
return -1;
@@ -1129,14 +1152,17 @@ bufferevent_openssl_new_impl(struct event_base *base,
switch (state) {
case BUFFEREVENT_SSL_ACCEPTING:
SSL_set_accept_state(bev_ssl->ssl);
- set_handshake_callbacks(bev_ssl, fd);
+ if (set_handshake_callbacks(bev_ssl, fd) < 0)
+ goto err;
break;
case BUFFEREVENT_SSL_CONNECTING:
SSL_set_connect_state(bev_ssl->ssl);
- set_handshake_callbacks(bev_ssl, fd);
+ if (set_handshake_callbacks(bev_ssl, fd) < 0)
+ goto err;
break;
case BUFFEREVENT_SSL_OPEN:
- set_open_callbacks(bev_ssl, fd);
+ if (set_open_callbacks(bev_ssl, fd) < 0)
+ goto err;
break;
default:
goto err;
@@ -1148,8 +1174,10 @@ bufferevent_openssl_new_impl(struct event_base *base,
bev_ssl->bev.bev.enabled = EV_READ|EV_WRITE;
if (bev_ssl->fd_is_set) {
/* XXX Is this quite right? */
- event_add(&bev_ssl->bev.bev.ev_read, NULL);
- event_add(&bev_ssl->bev.bev.ev_write, NULL);
+ if (event_add(&bev_ssl->bev.bev.ev_read, NULL) < 0)
+ goto err;
+ if (event_add(&bev_ssl->bev.bev.ev_write, NULL) < 0)
+ goto err;
}
}
diff --git a/bufferevent_pair.c b/bufferevent_pair.c
index 34880462..fc00a7c2 100644
--- a/bufferevent_pair.c
+++ b/bufferevent_pair.c
@@ -226,7 +226,8 @@ be_pair_enable(struct bufferevent *bufev, short events)
incref_and_lock(bufev);
- _bufferevent_generic_adj_timeouts(bufev);
+ if (_bufferevent_generic_adj_timeouts(bufev) < 0)
+ return -1;
/* We're starting to read! Does the other side have anything to write?*/
if ((events & EV_READ) && partner &&
@@ -245,8 +246,7 @@ be_pair_enable(struct bufferevent *bufev, short events)
static int
be_pair_disable(struct bufferevent *bev, short events)
{
- _bufferevent_generic_adj_timeouts(bev);
- return 0;
+ return _bufferevent_generic_adj_timeouts(bev);
}
static void
diff --git a/bufferevent_ratelim.c b/bufferevent_ratelim.c
index 968168ad..bbbadcad 100644
--- a/bufferevent_ratelim.c
+++ b/bufferevent_ratelim.c
@@ -256,6 +256,8 @@ _bufferevent_get_write_max(struct bufferevent_private *bev)
int
_bufferevent_decrement_read_buckets(struct bufferevent_private *bev, int bytes)
{
+ /* XXXXX Make sure all users of this function check its return value */
+ int r = 0;
/* need to hold lock on bev */
if (!bev->rate_limiting)
return 0;
@@ -264,8 +266,9 @@ _bufferevent_decrement_read_buckets(struct bufferevent_private *bev, int bytes)
bev->rate_limiting->limit.read_limit -= bytes;
if (bev->rate_limiting->limit.read_limit <= 0) {
bufferevent_suspend_read(&bev->bev, BEV_SUSPEND_BW);
- event_add(&bev->rate_limiting->refill_bucket_event,
- &bev->rate_limiting->cfg->tick_timeout);
+ if (event_add(&bev->rate_limiting->refill_bucket_event,
+ &bev->rate_limiting->cfg->tick_timeout) < 0)
+ r = -1;
}
}
@@ -278,12 +281,14 @@ _bufferevent_decrement_read_buckets(struct bufferevent_private *bev, int bytes)
UNLOCK_GROUP(bev->rate_limiting->group);
}
- return 0;
+ return r;
}
int
_bufferevent_decrement_write_buckets(struct bufferevent_private *bev, int bytes)
{
+ /* XXXXX Make sure all users of this function check its return value */
+ int r = 0;
/* need to hold lock */
if (!bev->rate_limiting)
return 0;
@@ -292,8 +297,9 @@ _bufferevent_decrement_write_buckets(struct bufferevent_private *bev, int bytes)
bev->rate_limiting->limit.write_limit -= bytes;
if (bev->rate_limiting->limit.write_limit <= 0) {
bufferevent_suspend_write(&bev->bev, BEV_SUSPEND_BW);
- event_add(&bev->rate_limiting->refill_bucket_event,
- &bev->rate_limiting->cfg->tick_timeout);
+ if (event_add(&bev->rate_limiting->refill_bucket_event,
+ &bev->rate_limiting->cfg->tick_timeout) < 0)
+ r = -1;
}
}
@@ -306,7 +312,7 @@ _bufferevent_decrement_write_buckets(struct bufferevent_private *bev, int bytes)
UNLOCK_GROUP(bev->rate_limiting->group);
}
- return 0;
+ return r;
}
/** Stop reading on every bufferevent in <b>g</b> */
@@ -395,6 +401,7 @@ _bev_refill_callback(evutil_socket_t fd, short what, void *arg)
XXXX if we need to be quiet for more ticks, we should
maybe figure out what timeout we really want.
*/
+ /* XXXX Handle event_add failure somehow */
event_add(&bev->rate_limiting->refill_bucket_event,
&bev->rate_limiting->cfg->tick_timeout);
}
@@ -579,6 +586,7 @@ bufferevent_rate_limit_group_new(struct event_base *base,
g->min_share = 64;
event_assign(&g->master_refill_event, base, -1, EV_PERSIST,
_bev_group_refill_callback, g);
+ /*XXXX handle event_add failure */
event_add(&g->master_refill_event, &cfg->tick_timeout);
EVTHREAD_ALLOC_LOCK(g->lock, EVTHREAD_LOCKTYPE_RECURSIVE);
diff --git a/bufferevent_sock.c b/bufferevent_sock.c
index 30bc44bc..36893a75 100644
--- a/bufferevent_sock.c
+++ b/bufferevent_sock.c
@@ -78,7 +78,7 @@
static int be_socket_enable(struct bufferevent *, short);
static int be_socket_disable(struct bufferevent *, short);
static void be_socket_destruct(struct bufferevent *);
-static void be_socket_adj_timeouts(struct bufferevent *);
+static int be_socket_adj_timeouts(struct bufferevent *);
static int be_socket_flush(struct bufferevent *, short, enum bufferevent_flush_mode);
static int be_socket_ctrl(struct bufferevent *, enum bufferevent_ctrl_op, union bufferevent_ctrl_data *);
@@ -111,6 +111,7 @@ bufferevent_socket_outbuf_cb(struct evbuffer *buf,
/* Somebody added data to the buffer, and we would like to
* write, and we were not writing. So, start writing. */
be_socket_add(&bufev->ev_write, &bufev->timeout_write);
+ /* XXXX handle failure from be_socket_add */
}
}
@@ -539,13 +540,17 @@ be_socket_destruct(struct bufferevent *bufev)
EVUTIL_CLOSESOCKET(fd);
}
-static void
+static int
be_socket_adj_timeouts(struct bufferevent *bufev)
{
+ int r = 0;
if (event_pending(&bufev->ev_read, EV_READ, NULL))
- be_socket_add(&bufev->ev_read, &bufev->timeout_read);
+ if (be_socket_add(&bufev->ev_read, &bufev->timeout_read) < 0)
+ r = -1;
if (event_pending(&bufev->ev_write, EV_WRITE, NULL))
- be_socket_add(&bufev->ev_write, &bufev->timeout_write);
+ if (be_socket_add(&bufev->ev_write, &bufev->timeout_write) < 0)
+ r = -1;
+ return r;
}
static int
diff --git a/evdns.c b/evdns.c
index 0d3906d4..fdf7026e 100644
--- a/evdns.c
+++ b/evdns.c
@@ -4113,11 +4113,11 @@ evdns_getaddrinfo_timeout_cb(evutil_socket_t fd, short what, void *ptr)
free_getaddrinfo_request(data);
}
-static void
+static int
evdns_getaddrinfo_set_timeout(struct evdns_base *evdns_base,
struct evdns_getaddrinfo_request *data)
{
- event_add(&data->timeout, &evdns_base->global_getaddrinfo_allow_skew);
+ return event_add(&data->timeout, &evdns_base->global_getaddrinfo_allow_skew);
}
static void
@@ -4178,6 +4178,7 @@ evdns_getaddrinfo_gotresolve(int result, char type, int count,
if (other_req->r) {
/* The other request is still working; maybe it will
* succeed. */
+ /* XXXX handle failure from set_timeout */
evdns_getaddrinfo_set_timeout(data->evdns_base, data);
data->pending_error = err;
return;
@@ -4243,6 +4244,7 @@ evdns_getaddrinfo_gotresolve(int result, char type, int count,
if (other_req->r) {
/* The other request is still in progress; wait for it */
+ /* XXXX handle failure from set_timeout */
evdns_getaddrinfo_set_timeout(data->evdns_base, data);
data->pending_result = res;
return;
diff --git a/http.c b/http.c
index ec47d13c..0c742c1c 100644
--- a/http.c
+++ b/http.c
@@ -303,7 +303,7 @@ evhttp_response_needs_body(struct evhttp_request *req)
req->type != EVHTTP_REQ_HEAD);
}
-static void
+static int
evhttp_add_event(struct event *ev, int timeout, int default_timeout)
{
if (timeout != 0) {
@@ -311,9 +311,9 @@ evhttp_add_event(struct event *ev, int timeout, int default_timeout)
evutil_timerclear(&tv);
tv.tv_sec = timeout != -1 ? timeout : default_timeout;
- event_add(ev, &tv);
+ return event_add(ev, &tv);
} else {
- event_add(ev, NULL);
+ return event_add(ev, NULL);
}
}
@@ -1067,6 +1067,7 @@ evhttp_connection_cb_cleanup(struct evhttp_connection *evcon)
{
if (evcon->retry_max < 0 || evcon->retry_cnt < evcon->retry_max) {
evtimer_assign(&evcon->retry_ev, evcon->base, evhttp_connection_retry, evcon);
+ /* XXXX handle failure from evhttp_add_event */
evhttp_add_event(&evcon->retry_ev,
MIN(3600, 2 << evcon->retry_cnt),
HTTP_CONNECT_TIMEOUT);
diff --git a/include/event2/bufferevent.h b/include/event2/bufferevent.h
index 48d56bd6..2b8bb6f6 100644
--- a/include/event2/bufferevent.h
+++ b/include/event2/bufferevent.h
@@ -371,7 +371,7 @@ short bufferevent_get_enabled(struct bufferevent *bufev);
@param timeout_read the read timeout, or NULL
@param timeout_write the write timeout, or NULL
*/
-void bufferevent_set_timeouts(struct bufferevent *bufev,
+int bufferevent_set_timeouts(struct bufferevent *bufev,
const struct timeval *timeout_read, const struct timeval *timeout_write);
/**