diff options
-rw-r--r-- | bufferevent-internal.h | 3 | ||||
-rw-r--r-- | bufferevent.c | 15 | ||||
-rw-r--r-- | bufferevent_async.c | 18 | ||||
-rw-r--r-- | bufferevent_filter.c | 1 | ||||
-rw-r--r-- | bufferevent_openssl.c | 1 | ||||
-rw-r--r-- | bufferevent_sock.c | 1 |
6 files changed, 36 insertions, 3 deletions
diff --git a/bufferevent-internal.h b/bufferevent-internal.h index dc471720..de1ff973 100644 --- a/bufferevent-internal.h +++ b/bufferevent-internal.h @@ -197,7 +197,8 @@ struct bufferevent_private { enum bufferevent_ctrl_op { BEV_CTRL_SET_FD, BEV_CTRL_GET_FD, - BEV_CTRL_GET_UNDERLYING + BEV_CTRL_GET_UNDERLYING, + BEV_CTRL_CANCEL_ALL }; /** Possible data types for a control callback */ diff --git a/bufferevent.c b/bufferevent.c index 9855d183..93a08015 100644 --- a/bufferevent.c +++ b/bufferevent.c @@ -59,6 +59,9 @@ #include "evbuffer-internal.h" #include "util-internal.h" +static void _bufferevent_cancel_all(struct bufferevent *bev); + + void bufferevent_suspend_read(struct bufferevent *bufev, bufferevent_suspend_flags what) { @@ -674,6 +677,7 @@ bufferevent_free(struct bufferevent *bufev) { BEV_LOCK(bufev); bufferevent_setcb(bufev, NULL, NULL, NULL, NULL); + _bufferevent_cancel_all(bufev); _bufferevent_decref_and_unlock(bufev); } @@ -750,6 +754,17 @@ bufferevent_getfd(struct bufferevent *bev) return (res<0) ? -1 : d.fd; } +static void +_bufferevent_cancel_all(struct bufferevent *bev) +{ + union bufferevent_ctrl_data d; + memset(&d, 0, sizeof(d)); + BEV_LOCK(bev); + if (bev->be_ops->ctrl) + bev->be_ops->ctrl(bev, BEV_CTRL_CANCEL_ALL, &d); + BEV_UNLOCK(bev); +} + short bufferevent_get_enabled(struct bufferevent *bufev) { diff --git a/bufferevent_async.c b/bufferevent_async.c index 9416e31f..a3b3ab1e 100644 --- a/bufferevent_async.c +++ b/bufferevent_async.c @@ -268,8 +268,8 @@ bev_async_consider_reading(struct bufferevent_async *beva) bufferevent_incref(bev); if (evbuffer_launch_read(bev->input, at_most, &beva->read_overlapped)) { beva->ok = 0; - bufferevent_decref(bev); _bufferevent_run_eventcb(bev, BEV_EVENT_ERROR); + bufferevent_decref(bev); } else { beva->read_in_progress = at_most; _bufferevent_decrement_read_buckets(&beva->bev, at_most); @@ -379,8 +379,10 @@ be_async_destruct(struct bufferevent *bev) bev_async_del_write(bev_async); fd = _evbuffer_overlapped_get_fd(bev->input); - if (bev_p->options & BEV_OPT_CLOSE_ON_FREE) + if (bev_p->options & BEV_OPT_CLOSE_ON_FREE) { + /* XXXX possible double-close */ evutil_closesocket(fd); + } /* delete this in case non-blocking connect was used */ if (event_initialized(&bev->ev_write)) { event_del(&bev->ev_write); @@ -669,8 +671,20 @@ be_async_ctrl(struct bufferevent *bev, enum bufferevent_ctrl_op op, _evbuffer_overlapped_set_fd(bev->output, data->fd); return 0; } + case BEV_CTRL_CANCEL_ALL: { + struct bufferevent_async *bev_a = upcast(bev); + evutil_socket_t fd = _evbuffer_overlapped_get_fd(bev->input); + if (fd != (evutil_socket_t)INVALID_SOCKET && + (bev_a->bev.options & BEV_OPT_CLOSE_ON_FREE)) { + closesocket(fd); + } + bev_a->ok = 0; + return 0; + } case BEV_CTRL_GET_UNDERLYING: default: return -1; } } + + diff --git a/bufferevent_filter.c b/bufferevent_filter.c index 7f19eb9a..234204fc 100644 --- a/bufferevent_filter.c +++ b/bufferevent_filter.c @@ -504,6 +504,7 @@ be_filter_ctrl(struct bufferevent *bev, enum bufferevent_ctrl_op op, return 0; case BEV_CTRL_GET_FD: case BEV_CTRL_SET_FD: + case BEV_CTRL_CANCEL_ALL: default: return -1; } diff --git a/bufferevent_openssl.c b/bufferevent_openssl.c index c5d242ea..da50c600 100644 --- a/bufferevent_openssl.c +++ b/bufferevent_openssl.c @@ -1167,6 +1167,7 @@ be_openssl_ctrl(struct bufferevent *bev, return -1; data->ptr = bev_ssl->underlying; return 0; + case BEV_CTRL_CANCEL_ALL: default: return -1; } diff --git a/bufferevent_sock.c b/bufferevent_sock.c index 975b5b6c..089aedb4 100644 --- a/bufferevent_sock.c +++ b/bufferevent_sock.c @@ -685,6 +685,7 @@ be_socket_ctrl(struct bufferevent *bev, enum bufferevent_ctrl_op op, data->fd = event_get_fd(&bev->ev_read); return 0; case BEV_CTRL_GET_UNDERLYING: + case BEV_CTRL_CANCEL_ALL: default: return -1; } |