From 9a0a3a3e6510b67c378aade2e8e6097b70ff6daa Mon Sep 17 00:00:00 2001 From: Azat Khuzhin Date: Mon, 16 Jan 2017 02:31:54 +0300 Subject: [PATCH] be: fix with filtered bufferevents and connect() without EAGAIN With filtered bufferevents (i.e. not real one, that have socket), we can trigger incorrect callback in this case. Let's look at example with http and bufferevent_openssl_filter_new(): - bev = bufferevent_openssl_filter_new() - http layer trying to connect() to localhost with bev # at this time, bev have writecb/readcb NULL but ev_write/ev_read has # timeout with 45 secs, default HTTP connect timeout - and when connect() retruns without EAGAIN (BSD'ism) we called event_active() before (with EV_WRITE), and this will call ev_write timeout only, while it is more correct to act on bufferevent instead of plain event, so let's trigger EV_WRITE for bufferevent which will do the job (and let's do this deferred). Fixes: http/https_simple # under solaris --- bufferevent_sock.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/bufferevent_sock.c b/bufferevent_sock.c index 58095f37..93aedb33 100644 --- a/bufferevent_sock.c +++ b/bufferevent_sock.c @@ -249,8 +249,8 @@ bufferevent_writecb(evutil_socket_t fd, short event, void *arg) /* we need to fake the error if the connection was refused * immediately - usually connection to localhost on BSD */ if (bufev_p->connection_refused) { - bufev_p->connection_refused = 0; - c = -1; + bufev_p->connection_refused = 0; + c = -1; } if (c == 0) @@ -438,13 +438,12 @@ bufferevent_socket_connect(struct bufferevent *bev, /* The connect succeeded already. How very BSD of it. */ result = 0; bufev_p->connecting = 1; - event_active(&bev->ev_write, EV_WRITE, 1); + bufferevent_trigger_nolock_(bev, EV_WRITE, BEV_OPT_DEFER_CALLBACKS); } else { /* The connect failed already. How very BSD of it. */ - bufev_p->connection_refused = 1; - bufev_p->connecting = 1; result = 0; - event_active(&bev->ev_write, EV_WRITE, 1); + bufferevent_run_eventcb_(bev, BEV_EVENT_ERROR, BEV_OPT_DEFER_CALLBACKS); + bufferevent_disable(bev, EV_WRITE|EV_READ); } goto done;