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.
This commit is contained in:
Nick Mathewson 2010-01-22 16:14:49 -05:00
parent 7296971b10
commit ff3f6cd42b
10 changed files with 145 additions and 89 deletions

View File

@ -219,7 +219,7 @@ struct bufferevent_ops {
void (*destruct)(struct bufferevent *); void (*destruct)(struct bufferevent *);
/** Called when the timeouts on the bufferevent have changed.*/ /** Called when the timeouts on the bufferevent have changed.*/
void (*adj_timeouts)(struct bufferevent *); int (*adj_timeouts)(struct bufferevent *);
/** Called to flush data. */ /** Called to flush data. */
int (*flush)(struct bufferevent *, short, enum bufferevent_flush_mode); 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); void _bufferevent_init_generic_timeout_cbs(struct bufferevent *bev);
/** Internal use: Delete the ev_read and ev_write callbacks if they're pending. /** Internal use: Delete the ev_read and ev_write callbacks if they're pending.
* Call this from the destructor function. */ * 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. /** 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 * (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, * 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. */ * 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 /** Internal use: We have just successfully read data into an inbuf, so
* reset the read timeout (if any). */ * reset the read timeout (if any). */

View File

@ -370,11 +370,12 @@ bufferevent_enable(struct bufferevent *bufev, short event)
return r; return r;
} }
void int
bufferevent_set_timeouts(struct bufferevent *bufev, bufferevent_set_timeouts(struct bufferevent *bufev,
const struct timeval *tv_read, const struct timeval *tv_read,
const struct timeval *tv_write) const struct timeval *tv_write)
{ {
int r = 0;
BEV_LOCK(bufev); BEV_LOCK(bufev);
if (tv_read) { if (tv_read) {
bufev->timeout_read = *tv_read; bufev->timeout_read = *tv_read;
@ -388,8 +389,10 @@ bufferevent_set_timeouts(struct bufferevent *bufev,
} }
if (bufev->be_ops->adj_timeouts) if (bufev->be_ops->adj_timeouts)
bufev->be_ops->adj_timeouts(bufev); r = bufev->be_ops->adj_timeouts(bufev);
BEV_UNLOCK(bufev); BEV_UNLOCK(bufev);
return r;
} }
@ -687,26 +690,34 @@ _bufferevent_init_generic_timeout_cbs(struct bufferevent *bev)
bufferevent_generic_write_timeout_cb, bev); bufferevent_generic_write_timeout_cb, bev);
} }
void int
_bufferevent_del_generic_timeout_cbs(struct bufferevent *bev) _bufferevent_del_generic_timeout_cbs(struct bufferevent *bev)
{ {
event_del(&bev->ev_read); int r1,r2;
event_del(&bev->ev_write); 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) _bufferevent_generic_adj_timeouts(struct bufferevent *bev)
{ {
const short enabled = bev->enabled; const short enabled = bev->enabled;
int r1=0, r2=0;
if ((enabled & EV_READ) && evutil_timerisset(&bev->timeout_read)) 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 else
event_del(&bev->ev_read); r1 = event_del(&bev->ev_read);
if ((enabled & EV_WRITE) && evutil_timerisset(&bev->timeout_write)) 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 else
event_del(&bev->ev_write); r2 = event_del(&bev->ev_write);
if (r1 < 0 || r2 < 0)
return -1;
return 0;
} }
int int

View File

@ -242,7 +242,8 @@ be_async_enable(struct bufferevent *buf, short what)
return -1; return -1;
/* NOTE: This interferes with non-blocking connect */ /* 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 /* If we newly enable reading or writing, and we aren't reading or
writing already, consider launching a new read or write. */ writing already, consider launching a new read or write. */

View File

@ -317,7 +317,7 @@ struct bufferevent_openssl {
static int be_openssl_enable(struct bufferevent *, short); static int be_openssl_enable(struct bufferevent *, short);
static int be_openssl_disable(struct bufferevent *, short); static int be_openssl_disable(struct bufferevent *, short);
static void be_openssl_destruct(struct bufferevent *); 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, static int be_openssl_flush(struct bufferevent *bufev,
short iotype, enum bufferevent_flush_mode mode); short iotype, enum bufferevent_flush_mode mode);
static int be_openssl_ctrl(struct bufferevent *, enum bufferevent_ctrl_op, union bufferevent_ctrl_data *); 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 /* Have the base communications channel (either the underlying bufferevent or
* ev_read and ev_write) start reading. Take the read-blocked-on-write flag * ev_read and ev_write) start reading. Take the read-blocked-on-write flag
* into account. */ * into account. */
static void static int
start_reading(struct bufferevent_openssl *bev_ssl) start_reading(struct bufferevent_openssl *bev_ssl)
{ {
if (bev_ssl->underlying) { if (bev_ssl->underlying) {
short e = EV_READ; short e = EV_READ;
if (bev_ssl->read_blocked_on_write) if (bev_ssl->read_blocked_on_write)
e |= EV_WRITE; e |= EV_WRITE;
bufferevent_enable(bev_ssl->underlying, e); return bufferevent_enable(bev_ssl->underlying, e);
} else { } else {
struct bufferevent *bev = &bev_ssl->bev.bev; struct bufferevent *bev = &bev_ssl->bev.bev;
_bufferevent_add_event(&bev->ev_read, &bev->timeout_read); int r;
if (bev_ssl->read_blocked_on_write) r = _bufferevent_add_event(&bev->ev_read, &bev->timeout_read);
_bufferevent_add_event(&bev->ev_write, if (r == 0 && bev_ssl->read_blocked_on_write)
r = _bufferevent_add_event(&bev->ev_write,
&bev->timeout_write); &bev->timeout_write);
return r;
} }
} }
/* Have the base communications channel (either the underlying bufferevent or /* Have the base communications channel (either the underlying bufferevent or
* ev_read and ev_write) start writing. Take the write-blocked-on-read flag * ev_read and ev_write) start writing. Take the write-blocked-on-read flag
* into account. */ * into account. */
static void static int
start_writing(struct bufferevent_openssl *bev_ssl) start_writing(struct bufferevent_openssl *bev_ssl)
{ {
int r;
if (bev_ssl->underlying) { if (bev_ssl->underlying) {
short e = EV_WRITE; short e = EV_WRITE;
if (bev_ssl->write_blocked_on_read) if (bev_ssl->write_blocked_on_read)
e |= EV_READ; e |= EV_READ;
bufferevent_enable(bev_ssl->underlying, e); r = bufferevent_enable(bev_ssl->underlying, e);
} else { } else {
struct bufferevent *bev = &bev_ssl->bev.bev; struct bufferevent *bev = &bev_ssl->bev.bev;
_bufferevent_add_event(&bev->ev_write, &bev->timeout_write); r = _bufferevent_add_event(&bev->ev_write, &bev->timeout_write);
if (bev_ssl->write_blocked_on_read) if (!r && bev_ssl->write_blocked_on_read)
_bufferevent_add_event(&bev->ev_read, r = _bufferevent_add_event(&bev->ev_read,
&bev->timeout_read); &bev->timeout_read);
} }
return r;
} }
static void static void
@ -426,45 +430,49 @@ stop_writing(struct bufferevent_openssl *bev_ssl)
} }
} }
static void static int
set_rbow(struct bufferevent_openssl *bev_ssl) set_rbow(struct bufferevent_openssl *bev_ssl)
{ {
if (!bev_ssl->underlying) if (!bev_ssl->underlying)
stop_reading(bev_ssl); stop_reading(bev_ssl);
bev_ssl->read_blocked_on_write = 1; 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) set_wbor(struct bufferevent_openssl *bev_ssl)
{ {
if (!bev_ssl->underlying) if (!bev_ssl->underlying)
stop_writing(bev_ssl); stop_writing(bev_ssl);
bev_ssl->write_blocked_on_read = 1; 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) clear_rbow(struct bufferevent_openssl *bev_ssl)
{ {
struct bufferevent *bev = &bev_ssl->bev.bev; struct bufferevent *bev = &bev_ssl->bev.bev;
int r = 0;
bev_ssl->read_blocked_on_write = 0; bev_ssl->read_blocked_on_write = 0;
if (!(bev->enabled & EV_WRITE)) if (!(bev->enabled & EV_WRITE))
stop_writing(bev_ssl); stop_writing(bev_ssl);
if (bev->enabled & EV_READ) 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) clear_wbor(struct bufferevent_openssl *bev_ssl)
{ {
struct bufferevent *bev = &bev_ssl->bev.bev; struct bufferevent *bev = &bev_ssl->bev.bev;
int r = 0;
bev_ssl->write_blocked_on_read = 0; bev_ssl->write_blocked_on_read = 0;
if (!(bev->enabled & EV_READ)) if (!(bev->enabled & EV_READ))
stop_reading(bev_ssl); stop_reading(bev_ssl);
if (bev->enabled & EV_WRITE) if (bev->enabled & EV_WRITE)
start_writing(bev_ssl); r = start_writing(bev_ssl);
return r;
} }
static void 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); r = SSL_read(bev_ssl->ssl, space[i].iov_base, space[i].iov_len);
if (r>0) { if (r>0) {
if (bev_ssl->read_blocked_on_write) if (bev_ssl->read_blocked_on_write)
clear_rbow(bev_ssl); if (clear_rbow(bev_ssl) < 0)
return -1;
++n_used; ++n_used;
space[i].iov_len = r; space[i].iov_len = r;
/* Not exactly right; we probably want to do /* 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: case SSL_ERROR_WANT_READ:
/* Can't read until underlying has more data. */ /* Can't read until underlying has more data. */
if (bev_ssl->read_blocked_on_write) if (bev_ssl->read_blocked_on_write)
clear_rbow(bev_ssl); if (clear_rbow(bev_ssl) < 0)
return -1;
break; break;
case SSL_ERROR_WANT_WRITE: case SSL_ERROR_WANT_WRITE:
/* This read operation requires a write, and the /* This read operation requires a write, and the
* underlying is full */ * underlying is full */
if (!bev_ssl->read_blocked_on_write) if (!bev_ssl->read_blocked_on_write)
set_rbow(bev_ssl); if (set_rbow(bev_ssl) < 0)
return -1;
break; break;
default: default:
conn_closed(bev_ssl, err, r); conn_closed(bev_ssl, err, r);
@ -610,7 +621,8 @@ do_write(struct bufferevent_openssl *bev_ssl, int atmost)
space[i].iov_len); space[i].iov_len);
if (r > 0) { if (r > 0) {
if (bev_ssl->write_blocked_on_read) if (bev_ssl->write_blocked_on_read)
clear_wbor(bev_ssl); if (clear_wbor(bev_ssl) < 0)
return -1;
n_written += r; n_written += r;
bev_ssl->last_write = -1; bev_ssl->last_write = -1;
/* Not exactly right; we probably want to do /* 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: case SSL_ERROR_WANT_WRITE:
/* Can't read until underlying has more data. */ /* Can't read until underlying has more data. */
if (bev_ssl->write_blocked_on_read) 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; bev_ssl->last_write = space[i].iov_len;
break; break;
case SSL_ERROR_WANT_READ: case SSL_ERROR_WANT_READ:
/* This read operation requires a write, and the /* This read operation requires a write, and the
* underlying is full */ * underlying is full */
if (!bev_ssl->write_blocked_on_read) 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; bev_ssl->last_write = space[i].iov_len;
break; break;
default: default:
@ -786,16 +800,17 @@ be_openssl_writeeventcb(evutil_socket_t fd, short what, void *ptr)
_bufferevent_decref_and_unlock(&bev_ssl->bev.bev); _bufferevent_decref_and_unlock(&bev_ssl->bev.bev);
} }
static void static int
set_open_callbacks(struct bufferevent_openssl *bev_ssl, evutil_socket_t fd) set_open_callbacks(struct bufferevent_openssl *bev_ssl, evutil_socket_t fd)
{ {
if (bev_ssl->underlying) { if (bev_ssl->underlying) {
bufferevent_setcb(bev_ssl->underlying, bufferevent_setcb(bev_ssl->underlying,
be_openssl_readcb, be_openssl_writecb, be_openssl_eventcb, be_openssl_readcb, be_openssl_writecb, be_openssl_eventcb,
bev_ssl); bev_ssl);
return 0;
} else { } else {
struct bufferevent *bev = &bev_ssl->bev.bev; 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) if (fd < 0 && bev_ssl->fd_is_set)
fd = event_get_fd(&bev->ev_read); fd = event_get_fd(&bev->ev_read);
if (bev_ssl->fd_is_set) { 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, event_assign(&bev->ev_write, bev->ev_base, fd,
EV_WRITE|EV_PERSIST, be_openssl_writeeventcb, bev_ssl); EV_WRITE|EV_PERSIST, be_openssl_writeeventcb, bev_ssl);
if (rpending) if (rpending)
_bufferevent_add_event(&bev->ev_read, &bev->timeout_read); r1 = _bufferevent_add_event(&bev->ev_read, &bev->timeout_read);
if (wpending) if (wpending)
_bufferevent_add_event(&bev->ev_write, &bev->timeout_write); r2 = _bufferevent_add_event(&bev->ev_write, &bev->timeout_write);
if (fd >= 0) { if (fd >= 0) {
bev_ssl->fd_is_set = 1; 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) { if (r==1) {
/* We're done! */ /* We're done! */
bev_ssl->state = BUFFEREVENT_SSL_OPEN; 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 */ /* Call do_read and do_write as needed */
bufferevent_enable(&bev_ssl->bev.bev, bev_ssl->bev.bev.enabled); bufferevent_enable(&bev_ssl->bev.bev, bev_ssl->bev.bev.enabled);
_bufferevent_run_eventcb(&bev_ssl->bev.bev, _bufferevent_run_eventcb(&bev_ssl->bev.bev,
@ -850,13 +866,13 @@ do_handshake(struct bufferevent_openssl *bev_ssl)
case SSL_ERROR_WANT_WRITE: case SSL_ERROR_WANT_WRITE:
if (!bev_ssl->underlying) { if (!bev_ssl->underlying) {
stop_reading(bev_ssl); stop_reading(bev_ssl);
start_writing(bev_ssl); return start_writing(bev_ssl);
} }
return 0; return 0;
case SSL_ERROR_WANT_READ: case SSL_ERROR_WANT_READ:
if (!bev_ssl->underlying) { if (!bev_ssl->underlying) {
stop_writing(bev_ssl); stop_writing(bev_ssl);
start_reading(bev_ssl); return start_reading(bev_ssl);
} }
return 0; return 0;
default: default:
@ -870,7 +886,7 @@ static void
be_openssl_handshakecb(struct bufferevent *bev_base, void *ctx) be_openssl_handshakecb(struct bufferevent *bev_base, void *ctx)
{ {
struct bufferevent_openssl *bev_ssl = ctx; struct bufferevent_openssl *bev_ssl = ctx;
do_handshake(bev_ssl); do_handshake(bev_ssl);/* XXX handle failure */
} }
static void static void
@ -882,11 +898,11 @@ be_openssl_handshakeeventcb(evutil_socket_t fd, short what, void *ptr)
if (what & EV_TIMEOUT) { if (what & EV_TIMEOUT) {
_bufferevent_run_eventcb(&bev_ssl->bev.bev, BEV_EVENT_TIMEOUT); _bufferevent_run_eventcb(&bev_ssl->bev.bev, BEV_EVENT_TIMEOUT);
} else } else
do_handshake(bev_ssl); do_handshake(bev_ssl);/* XXX handle failure */
_bufferevent_decref_and_unlock(&bev_ssl->bev.bev); _bufferevent_decref_and_unlock(&bev_ssl->bev.bev);
} }
static void static int
set_handshake_callbacks(struct bufferevent_openssl *bev_ssl, evutil_socket_t fd) set_handshake_callbacks(struct bufferevent_openssl *bev_ssl, evutil_socket_t fd)
{ {
if (bev_ssl->underlying) { 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_handshakecb, be_openssl_handshakecb,
be_openssl_eventcb, be_openssl_eventcb,
bev_ssl); bev_ssl);
do_handshake(bev_ssl); return do_handshake(bev_ssl);
} else { } else {
struct bufferevent *bev = &bev_ssl->bev.bev; struct bufferevent *bev = &bev_ssl->bev.bev;
int r1=0, r2=0;
if (fd < 0 && bev_ssl->fd_is_set) if (fd < 0 && bev_ssl->fd_is_set)
fd = event_get_fd(&bev->ev_read); fd = event_get_fd(&bev->ev_read);
if (bev_ssl->fd_is_set) { 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, event_assign(&bev->ev_write, bev->ev_base, fd,
EV_WRITE|EV_PERSIST, be_openssl_handshakeeventcb, bev_ssl); EV_WRITE|EV_PERSIST, be_openssl_handshakeeventcb, bev_ssl);
if (fd >= 0) { if (fd >= 0) {
_bufferevent_add_event(&bev->ev_read, &bev->timeout_read); r1 = _bufferevent_add_event(&bev->ev_read, &bev->timeout_read);
_bufferevent_add_event(&bev->ev_write, &bev->timeout_write); r2 = _bufferevent_add_event(&bev->ev_write, &bev->timeout_write);
bev_ssl->fd_is_set = 1; 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) if (SSL_renegotiate(bev_ssl->ssl) < 0)
return -1; return -1;
bev_ssl->state = BUFFEREVENT_SSL_CONNECTING; 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) if (!bev_ssl->underlying)
do_handshake(bev_ssl); return do_handshake(bev_ssl);
return 0; return 0;
} }
@ -935,14 +954,16 @@ be_openssl_outbuf_cb(struct evbuffer *buf,
const struct evbuffer_cb_info *cbinfo, void *arg) const struct evbuffer_cb_info *cbinfo, void *arg)
{ {
struct bufferevent_openssl *bev_ssl = arg; struct bufferevent_openssl *bev_ssl = arg;
int r = 0;
/* XXX need to hold a reference here. */ /* XXX need to hold a reference here. */
if (cbinfo->n_added && bev_ssl->state == BUFFEREVENT_SSL_OPEN) { if (cbinfo->n_added && bev_ssl->state == BUFFEREVENT_SSL_OPEN) {
if (cbinfo->orig_size == 0) 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); &bev_ssl->bev.bev.timeout_write);
consider_writing(bev_ssl); consider_writing(bev_ssl);
} }
/* XXX Handle r < 0 */
} }
@ -950,14 +971,15 @@ static int
be_openssl_enable(struct bufferevent *bev, short events) be_openssl_enable(struct bufferevent *bev, short events)
{ {
struct bufferevent_openssl *bev_ssl = upcast(bev); struct bufferevent_openssl *bev_ssl = upcast(bev);
int r1 = 0, r2 = 0;
if (bev_ssl->state != BUFFEREVENT_SSL_OPEN) if (bev_ssl->state != BUFFEREVENT_SSL_OPEN)
return 0; return 0;
if (events & EV_READ) if (events & EV_READ)
start_reading(bev_ssl); r1 = start_reading(bev_ssl);
if (events & EV_WRITE) if (events & EV_WRITE)
start_writing(bev_ssl); r2 = start_writing(bev_ssl);
if (bev_ssl->underlying) { if (bev_ssl->underlying) {
_bufferevent_generic_adj_timeouts(bev); _bufferevent_generic_adj_timeouts(bev);
@ -967,7 +989,7 @@ be_openssl_enable(struct bufferevent *bev, short events)
if (events & EV_WRITE) if (events & EV_WRITE)
consider_writing(bev_ssl); consider_writing(bev_ssl);
} }
return 0; return (r1 < 0 || r2 < 0) ? -1 : 0;
} }
static int static int
@ -1008,18 +1030,20 @@ be_openssl_destruct(struct bufferevent *bev)
} }
} }
static void static int
be_openssl_adj_timeouts(struct bufferevent *bev) be_openssl_adj_timeouts(struct bufferevent *bev)
{ {
struct bufferevent_openssl *bev_ssl = upcast(bev); struct bufferevent_openssl *bev_ssl = upcast(bev);
if (bev_ssl->underlying) if (bev_ssl->underlying)
_bufferevent_generic_adj_timeouts(bev); return _bufferevent_generic_adj_timeouts(bev);
else { else {
int r1=0, r2=0;
if (event_pending(&bev->ev_read, EV_READ, NULL)) 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)) 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; bev_ssl->fd_is_set = 1;
} }
if (bev_ssl->state == BUFFEREVENT_SSL_OPEN) if (bev_ssl->state == BUFFEREVENT_SSL_OPEN)
set_open_callbacks(bev_ssl, data->fd); return set_open_callbacks(bev_ssl, data->fd);
else { else {
set_handshake_callbacks(bev_ssl, data->fd); return set_handshake_callbacks(bev_ssl, data->fd);
} }
return 0;
case BEV_CTRL_GET_FD: case BEV_CTRL_GET_FD:
if (bev_ssl->underlying) if (bev_ssl->underlying)
return -1; return -1;
@ -1129,14 +1152,17 @@ bufferevent_openssl_new_impl(struct event_base *base,
switch (state) { switch (state) {
case BUFFEREVENT_SSL_ACCEPTING: case BUFFEREVENT_SSL_ACCEPTING:
SSL_set_accept_state(bev_ssl->ssl); SSL_set_accept_state(bev_ssl->ssl);
set_handshake_callbacks(bev_ssl, fd); if (set_handshake_callbacks(bev_ssl, fd) < 0)
goto err;
break; break;
case BUFFEREVENT_SSL_CONNECTING: case BUFFEREVENT_SSL_CONNECTING:
SSL_set_connect_state(bev_ssl->ssl); SSL_set_connect_state(bev_ssl->ssl);
set_handshake_callbacks(bev_ssl, fd); if (set_handshake_callbacks(bev_ssl, fd) < 0)
goto err;
break; break;
case BUFFEREVENT_SSL_OPEN: case BUFFEREVENT_SSL_OPEN:
set_open_callbacks(bev_ssl, fd); if (set_open_callbacks(bev_ssl, fd) < 0)
goto err;
break; break;
default: default:
goto err; goto err;
@ -1148,8 +1174,10 @@ bufferevent_openssl_new_impl(struct event_base *base,
bev_ssl->bev.bev.enabled = EV_READ|EV_WRITE; bev_ssl->bev.bev.enabled = EV_READ|EV_WRITE;
if (bev_ssl->fd_is_set) { if (bev_ssl->fd_is_set) {
/* XXX Is this quite right? */ /* XXX Is this quite right? */
event_add(&bev_ssl->bev.bev.ev_read, NULL); if (event_add(&bev_ssl->bev.bev.ev_read, NULL) < 0)
event_add(&bev_ssl->bev.bev.ev_write, NULL); goto err;
if (event_add(&bev_ssl->bev.bev.ev_write, NULL) < 0)
goto err;
} }
} }

View File

@ -226,7 +226,8 @@ be_pair_enable(struct bufferevent *bufev, short events)
incref_and_lock(bufev); 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?*/ /* We're starting to read! Does the other side have anything to write?*/
if ((events & EV_READ) && partner && if ((events & EV_READ) && partner &&
@ -245,8 +246,7 @@ be_pair_enable(struct bufferevent *bufev, short events)
static int static int
be_pair_disable(struct bufferevent *bev, short events) be_pair_disable(struct bufferevent *bev, short events)
{ {
_bufferevent_generic_adj_timeouts(bev); return _bufferevent_generic_adj_timeouts(bev);
return 0;
} }
static void static void

View File

@ -256,6 +256,8 @@ _bufferevent_get_write_max(struct bufferevent_private *bev)
int int
_bufferevent_decrement_read_buckets(struct bufferevent_private *bev, int bytes) _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 */ /* need to hold lock on bev */
if (!bev->rate_limiting) if (!bev->rate_limiting)
return 0; return 0;
@ -264,8 +266,9 @@ _bufferevent_decrement_read_buckets(struct bufferevent_private *bev, int bytes)
bev->rate_limiting->limit.read_limit -= bytes; bev->rate_limiting->limit.read_limit -= bytes;
if (bev->rate_limiting->limit.read_limit <= 0) { if (bev->rate_limiting->limit.read_limit <= 0) {
bufferevent_suspend_read(&bev->bev, BEV_SUSPEND_BW); bufferevent_suspend_read(&bev->bev, BEV_SUSPEND_BW);
event_add(&bev->rate_limiting->refill_bucket_event, if (event_add(&bev->rate_limiting->refill_bucket_event,
&bev->rate_limiting->cfg->tick_timeout); &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); UNLOCK_GROUP(bev->rate_limiting->group);
} }
return 0; return r;
} }
int int
_bufferevent_decrement_write_buckets(struct bufferevent_private *bev, int bytes) _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 */ /* need to hold lock */
if (!bev->rate_limiting) if (!bev->rate_limiting)
return 0; return 0;
@ -292,8 +297,9 @@ _bufferevent_decrement_write_buckets(struct bufferevent_private *bev, int bytes)
bev->rate_limiting->limit.write_limit -= bytes; bev->rate_limiting->limit.write_limit -= bytes;
if (bev->rate_limiting->limit.write_limit <= 0) { if (bev->rate_limiting->limit.write_limit <= 0) {
bufferevent_suspend_write(&bev->bev, BEV_SUSPEND_BW); bufferevent_suspend_write(&bev->bev, BEV_SUSPEND_BW);
event_add(&bev->rate_limiting->refill_bucket_event, if (event_add(&bev->rate_limiting->refill_bucket_event,
&bev->rate_limiting->cfg->tick_timeout); &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); UNLOCK_GROUP(bev->rate_limiting->group);
} }
return 0; return r;
} }
/** Stop reading on every bufferevent in <b>g</b> */ /** 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 XXXX if we need to be quiet for more ticks, we should
maybe figure out what timeout we really want. maybe figure out what timeout we really want.
*/ */
/* XXXX Handle event_add failure somehow */
event_add(&bev->rate_limiting->refill_bucket_event, event_add(&bev->rate_limiting->refill_bucket_event,
&bev->rate_limiting->cfg->tick_timeout); &bev->rate_limiting->cfg->tick_timeout);
} }
@ -579,6 +586,7 @@ bufferevent_rate_limit_group_new(struct event_base *base,
g->min_share = 64; g->min_share = 64;
event_assign(&g->master_refill_event, base, -1, EV_PERSIST, event_assign(&g->master_refill_event, base, -1, EV_PERSIST,
_bev_group_refill_callback, g); _bev_group_refill_callback, g);
/*XXXX handle event_add failure */
event_add(&g->master_refill_event, &cfg->tick_timeout); event_add(&g->master_refill_event, &cfg->tick_timeout);
EVTHREAD_ALLOC_LOCK(g->lock, EVTHREAD_LOCKTYPE_RECURSIVE); EVTHREAD_ALLOC_LOCK(g->lock, EVTHREAD_LOCKTYPE_RECURSIVE);

View File

@ -78,7 +78,7 @@
static int be_socket_enable(struct bufferevent *, short); static int be_socket_enable(struct bufferevent *, short);
static int be_socket_disable(struct bufferevent *, short); static int be_socket_disable(struct bufferevent *, short);
static void be_socket_destruct(struct bufferevent *); 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_flush(struct bufferevent *, short, enum bufferevent_flush_mode);
static int be_socket_ctrl(struct bufferevent *, enum bufferevent_ctrl_op, union bufferevent_ctrl_data *); 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 /* Somebody added data to the buffer, and we would like to
* write, and we were not writing. So, start writing. */ * write, and we were not writing. So, start writing. */
be_socket_add(&bufev->ev_write, &bufev->timeout_write); 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); EVUTIL_CLOSESOCKET(fd);
} }
static void static int
be_socket_adj_timeouts(struct bufferevent *bufev) be_socket_adj_timeouts(struct bufferevent *bufev)
{ {
int r = 0;
if (event_pending(&bufev->ev_read, EV_READ, NULL)) 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)) 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 static int

View File

@ -4113,11 +4113,11 @@ evdns_getaddrinfo_timeout_cb(evutil_socket_t fd, short what, void *ptr)
free_getaddrinfo_request(data); free_getaddrinfo_request(data);
} }
static void static int
evdns_getaddrinfo_set_timeout(struct evdns_base *evdns_base, evdns_getaddrinfo_set_timeout(struct evdns_base *evdns_base,
struct evdns_getaddrinfo_request *data) 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 static void
@ -4178,6 +4178,7 @@ evdns_getaddrinfo_gotresolve(int result, char type, int count,
if (other_req->r) { if (other_req->r) {
/* The other request is still working; maybe it will /* The other request is still working; maybe it will
* succeed. */ * succeed. */
/* XXXX handle failure from set_timeout */
evdns_getaddrinfo_set_timeout(data->evdns_base, data); evdns_getaddrinfo_set_timeout(data->evdns_base, data);
data->pending_error = err; data->pending_error = err;
return; return;
@ -4243,6 +4244,7 @@ evdns_getaddrinfo_gotresolve(int result, char type, int count,
if (other_req->r) { if (other_req->r) {
/* The other request is still in progress; wait for it */ /* The other request is still in progress; wait for it */
/* XXXX handle failure from set_timeout */
evdns_getaddrinfo_set_timeout(data->evdns_base, data); evdns_getaddrinfo_set_timeout(data->evdns_base, data);
data->pending_result = res; data->pending_result = res;
return; return;

7
http.c
View File

@ -303,7 +303,7 @@ evhttp_response_needs_body(struct evhttp_request *req)
req->type != EVHTTP_REQ_HEAD); req->type != EVHTTP_REQ_HEAD);
} }
static void static int
evhttp_add_event(struct event *ev, int timeout, int default_timeout) evhttp_add_event(struct event *ev, int timeout, int default_timeout)
{ {
if (timeout != 0) { if (timeout != 0) {
@ -311,9 +311,9 @@ evhttp_add_event(struct event *ev, int timeout, int default_timeout)
evutil_timerclear(&tv); evutil_timerclear(&tv);
tv.tv_sec = timeout != -1 ? timeout : default_timeout; tv.tv_sec = timeout != -1 ? timeout : default_timeout;
event_add(ev, &tv); return event_add(ev, &tv);
} else { } 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) { if (evcon->retry_max < 0 || evcon->retry_cnt < evcon->retry_max) {
evtimer_assign(&evcon->retry_ev, evcon->base, evhttp_connection_retry, evcon); evtimer_assign(&evcon->retry_ev, evcon->base, evhttp_connection_retry, evcon);
/* XXXX handle failure from evhttp_add_event */
evhttp_add_event(&evcon->retry_ev, evhttp_add_event(&evcon->retry_ev,
MIN(3600, 2 << evcon->retry_cnt), MIN(3600, 2 << evcon->retry_cnt),
HTTP_CONNECT_TIMEOUT); HTTP_CONNECT_TIMEOUT);

View File

@ -371,7 +371,7 @@ short bufferevent_get_enabled(struct bufferevent *bufev);
@param timeout_read the read timeout, or NULL @param timeout_read the read timeout, or NULL
@param timeout_write the write 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); const struct timeval *timeout_read, const struct timeval *timeout_write);
/** /**