Hi all,
A few days ago I faced a big problem and could not solve it since then. I'll need your help and advice on this.
I'm working with asynchronous sockets and using kqueue as notification mechanism. I have no problems with asynchronously accepting new connections (on the server side) and can handle thousands of incoming connections in a fraction of a second.
However, when I try to use asynchronous connect, I'm not receiving a kqueue notification that the connection has been established. However, when my server disconnects this new client, I receive two notifications from kqueue (I assume that the first one is for connect, and the second one is for disconnect). But why is the first one delayed until the disconnect?
sockstat and other tools show that the connection was successful despite me not receiving kqueue notifications on the client side.
I cannot publish all the source code but happy to publish relevant parts of it if it is needed to solve the problem.
BTW I check every system call and log every error, but no errors are returned by any of the calls.
How I register my connecting socket with kqueue:
How I connect the socket:
The error it returns is EINPROGRESS (connection is pending).
How I check for kqueue notifications:
Timeout (ts_) is 100 ms.
And I call GetEvent() in the loop:
Obviously, the socket is non-blocking.
Any help and advice is much appreciated. I'm hitting the wall for last few days. Really need some fresh eyes on the problem.
Thanks in advance!
P.S. FreeBSD 9.1 64-bit RELEASE p6. Firewall disabled. I am running it in VirtualBox. I am using GCC 4.8.2 as a compiler (but it should not matter...).
A few days ago I faced a big problem and could not solve it since then. I'll need your help and advice on this.
I'm working with asynchronous sockets and using kqueue as notification mechanism. I have no problems with asynchronously accepting new connections (on the server side) and can handle thousands of incoming connections in a fraction of a second.
However, when I try to use asynchronous connect, I'm not receiving a kqueue notification that the connection has been established. However, when my server disconnects this new client, I receive two notifications from kqueue (I assume that the first one is for connect, and the second one is for disconnect). But why is the first one delayed until the disconnect?
sockstat and other tools show that the connection was successful despite me not receiving kqueue notifications on the client side.
I cannot publish all the source code but happy to publish relevant parts of it if it is needed to solve the problem.
BTW I check every system call and log every error, but no errors are returned by any of the calls.
How I register my connecting socket with kqueue:
Code:
const short filter = EVFILT_READ | EVFILT_WRITE | EVFILT_AIO;
struct kevent kev;
EV_SET(&kev, socket_handle, filter, EV_ADD, 0, 0, context_ptr);
const int rc = ::kevent(kqueue_, &kev, 1, nullptr, 0, nullptr);
if (rc == kCallFailed)
{
// log error here
return false;
}
return true;
How I connect the socket:
Code:
enum class AsyncResult { kSuccessCompleted, kSuccessPending, kFailure };
AsyncResult Connect()
{
const int rc = ::connect(socket_, reinterpret_cast<sockaddr *>(&end_points_.remote_address), sizeof(end_points_.remote_address));
if (rc == SOCKET_ERROR)
{
const int error = errno;
if (error != EINPROGRESS)
{
if (error == EISCONN)
return AsyncResult::kSuccessCompleted;
// log error here
return AsyncResult::kFailure;
}
return AsyncResult::kSuccessPending;
}
return AsyncResult::kSuccessCompleted;
}
The error it returns is EINPROGRESS (connection is pending).
How I check for kqueue notifications:
Code:
virtual bool GetEvent(IIoContext*& context_ptr, bool& is_timeout,
size_t &count) override
{
struct kevent evt;
(void)::memset(&evt, 0, sizeof(evt));
int collected_entry_count = 0;
do
{
collected_entry_count = ::kevent(kqueue_, nullptr, 0, &evt, 1, &ts_);
}
while ((collected_entry_count == 1) && (evt.udata == nullptr));
if (collected_entry_count != 1)
{
is_timeout = (collected_entry_count == 0);
if (!is_timeout)
{
// log error here
}
return false;
}
context_ptr = reinterpret_cast<IIoContext *>(evt.udata);
return true;
}
Timeout (ts_) is 100 ms.
And I call GetEvent() in the loop:
Code:
IIoContext* context_ptr = nullptr;
bool is_timeout = false;
size_t count = 0;;
while (!stopped_.load(std::memory_order_acquire))
{
const bool collected_ok = notifier_->GetEvent(context_ptr, is_timeout, count);
if (!collected_ok || (context_ptr == nullptr))
{
if (!is_timeout)
{
// logging error here
}
continue;
}
context_ptr->ProcessEvent(count);
}
Obviously, the socket is non-blocking.
Any help and advice is much appreciated. I'm hitting the wall for last few days. Really need some fresh eyes on the problem.
Thanks in advance!
P.S. FreeBSD 9.1 64-bit RELEASE p6. Firewall disabled. I am running it in VirtualBox. I am using GCC 4.8.2 as a compiler (but it should not matter...).