evpp
evpp copied to clipboard
Invalid FdChannel when gdb is attached
I have an evnsq
consumer application that connects to nsqd
. When the consumer is stopped by attaching gdb
it is expected that the TCP connection to nsqd
will break. But what I'm noticing is that libevent
sometimes makes a call to FdChannel::HandleEvent
with an invalid object in this scenario leading to a crash.
void FdChannel::HandleEvent(evpp_socket_t sockfd, short which, void* v) {
FdChannel* c = (FdChannel*)v;
c->HandleEvent(sockfd, which);
}
It appears that the callback is being made with an older channel object pointer (that has been disconnected most likely). I also see that evpp
actually creates a new channel, but somewhere libevent
still holds on to the older event handler.
Has anyone seen this issue before? If yes, what's the recommended solution? As of now, my consumer application crashes whenever I attach the debugger.
After some more digging, this is what is happening. The issue is not with libevent
calling back with an invalid FdChannel
object. The problem occurs when a debugger is attached and the thread processing the libevent
callback is stopped long enough that the TCP connection times out. Here's the sequence:
-
libevent
calls back intoFdChannel::HandleEvent
with both read and write bits set in the event.FdChannel::HandleEvent(evpp_socket_t sockfd, short which)
- The
read_fn_()
is then invoked
if ((which & kReadable) && read_fn_) {
read_fn_();
}
- But by this time the TCP connection has timed out, resulting in the TCP connection reset and destruction of the
FdChannel
object.
core.dll!evpp::FdChannel::~FdChannel() Line 23 C++
[External Code]
core.dll!evpp::Connector::~Connector() Line 43 C++
[External Code]
core.dll!evpp::TCPClient::Connect::__l2::<lambda>() Line 53 C++
[External Code]
core.dll!evpp::EventLoop::RunInLoop(std::function<void __cdecl(void)> && functor) Line 223 C++
core.dll!evpp::TCPClient::Connect() Line 56 C++
core.dll!evpp::TCPClient::Reconnect() Line 91 C++
core.dll!evpp::TCPClient::OnRemoveConnection(const std::shared_ptr<evpp::TCPConn> & c) Line 135 C++
[External Code]
core.dll!evpp::TCPConn::HandleClose() Line 282 C++
core.dll!evpp::TCPConn::HandleError() Line 290 C++
core.dll!evpp::TCPConn::HandleRead() Line 210 C++
- By the time control comes back to process the
write_fn_()
, theFdChannel
object has been destroyed, leading to the crash.
if ((which & kWritable) && write_fn_) {
write_fn_();
}