From ff3f6cd42b8d58d6db9c2ceb2cf9868d1a8f7ec0 Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Fri, 22 Jan 2010 16:14:49 -0500 Subject: [PATCH] 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. --- bufferevent-internal.h | 6 +- bufferevent.c | 31 +++++--- bufferevent_async.c | 3 +- bufferevent_openssl.c | 140 +++++++++++++++++++++-------------- bufferevent_pair.c | 6 +- bufferevent_ratelim.c | 20 +++-- bufferevent_sock.c | 13 +++- evdns.c | 6 +- http.c | 7 +- include/event2/bufferevent.h | 2 +- 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 g */ @@ -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); /** -- 2.40.0