[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]
Re: [Libevent-users] a bug of libevent(2.1.4-alpha) IOCP: socket is closed twice when bufferevent is freed
On Thu, Nov 20, 2014 at 03:06:59PM +0800, jason wrote:
> I ran into a strange situation where some new connections were randomly
> closed just after many client connections were closed. I finally get the
> reason after diving into source code and debugging for several hours.
>
>
>
> When bufferevent is freed, the internal socket is closed at be_async_ctrl().
>
>
> Call stack:
>
> > 51CY.exe!be_async_ctrl(bufferevent * bev, bufferevent_ctrl_op op,
> bufferevent_ctrl_data * data) Line 673 C
>
> 51CY.exe!bufferevent_cancel_all_(bufferevent * bev) Line 884 + 0x15
> bytes C
>
> 51CY.exe!bufferevent_free(bufferevent * bufev) Line 786 + 0x9 bytes
> C
>
> 51CY.exe!be_filter_unlink(bufferevent * bev) Line 234 + 0xf bytes
> C
>
> 51CY.exe!bufferevent_decref_and_unlock_(bufferevent * bufev) Line
> 696 + 0xf bytes C
>
> 51CY.exe!bufferevent_free(bufferevent * bufev) Line 787 + 0x9 bytes
> C
>
>
>
> Bufferevent_free() also forwards a event callback to event_base.
>
> Call stack:
>
> > 51CY.exe!event_callback_finalize_many_(event_base * base, int n_cbs,
> event_callback * * evcbs, void (event_callback *, void *)* cb) Line 2210
> C
>
> 51CY.exe!bufferevent_decref_and_unlock_(bufferevent * bufev) Line
> 713 + 0x18 bytes C
>
> 51CY.exe!bufferevent_free(bufferevent * bufev) Line 787 + 0x9 bytes
> C
>
>
>
> The same socket is secondly closed when the event callback is invoked in the
> next event_base loop.
>
> Callstack:
>
> > 51CYClient.exe!evutil_closesocket(int sock) Line 425 C
>
> 51CYClient.exe!be_async_destruct(bufferevent * bev) Line 386 + 0x9
> bytes C
>
> 51CYClient.exe!bufferevent_finalize_cb_(event_callback * evcb, void *
> arg_) Line 734 + 0xf bytes C
>
> 51CYClient.exe!event_process_active_single_queue(event_base * base,
> evcallback_list * activeq, int max_to_process, const timeval * endtime)
> Line 1604 + 0xe bytes C
>
> 51CYClient.exe!event_process_active(event_base * base) Line 1668 +
> 0x14 bytes C
>
> 51CYClient.exe!event_base_loop(event_base * base, int flags) Line
> 1890 + 0x9 bytes C
>
>
>
> So socket of new connection will be closed by this mean if the new socket
> handle value equals to the old one.
Hi Jason,
If I understand you correctly, the following patch must helps, could
please verify this?
diff --git a/bufferevent_async.c b/bufferevent_async.c
index f32573e..6395e57 100644
--- a/bufferevent_async.c
+++ b/bufferevent_async.c
@@ -381,9 +381,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) {
- /* XXXX possible double-close */
+ if (fd != (evutil_socket_t)INVALID_SOCKET &&
+ (bev_p->options & BEV_OPT_CLOSE_ON_FREE)) {
evutil_closesocket(fd);
+ evbuffer_overlapped_set_fd_(bev->input, INVALID_SOCKET);
}
}
@@ -671,6 +672,7 @@ be_async_ctrl(struct bufferevent *bev, enum bufferevent_ctrl_op op,
if (fd != (evutil_socket_t)INVALID_SOCKET &&
(bev_a->bev.options & BEV_OPT_CLOSE_ON_FREE)) {
closesocket(fd);
+ evbuffer_overlapped_set_fd_(bev->input, INVALID_SOCKET);
}
bev_a->ok = 0;
return 0;
(You email client could make patch un appliable I think, based on you
incoming email, if so would happen, let me know, I will resend as an
attachment).
***********************************************************************
To unsubscribe, send an e-mail to majordomo@xxxxxxxxxxxxx with
unsubscribe libevent-users in the body.