|
|
@@ -8,6 +8,7 @@
|
|
|
#include "bus.h"
|
|
|
#include "array.h"
|
|
|
#include "evtpoll.h"
|
|
|
+#include "core.h"
|
|
|
|
|
|
#include <winpr/file.h>
|
|
|
#include <winpr/handle.h>
|
|
|
@@ -16,6 +17,8 @@
|
|
|
#include <winpr/string.h>
|
|
|
#include <winpr/wlog.h>
|
|
|
|
|
|
+#include <sys/eventfd.h>
|
|
|
+
|
|
|
#define TAG TOOLKIT_TAG("ioqueue")
|
|
|
|
|
|
#ifndef SO_UPDATE_CONNECT_CONTEXT
|
|
|
@@ -39,7 +42,7 @@ struct ioqueue_t {
|
|
|
HANDLE iocp; //for build successfully temporary!!!!!!!!!!!!!!! TODO: delete it!!
|
|
|
|
|
|
evtpoll_t* ep;
|
|
|
-
|
|
|
+ int msg_fd;
|
|
|
void *user_data;
|
|
|
/* timer */
|
|
|
spinlock_t tm_queue_lock;
|
|
|
@@ -56,6 +59,7 @@ struct ioqueue_t {
|
|
|
};
|
|
|
|
|
|
typedef struct ioqueue_msg {
|
|
|
+ OVERLAPPED ov; /*it's bound to append this structure just for recognize its type.*/
|
|
|
int msg_type;
|
|
|
param_size_t param1;
|
|
|
param_size_t param2;
|
|
|
@@ -220,11 +224,13 @@ static int is_os_gte_xp() /* is os version greater and equal than xp */
|
|
|
|
|
|
static __inline LONG inc_msg_cnt(ioqueue_t *ioq)
|
|
|
{
|
|
|
+ //return ++ioq->msg_cnt;
|
|
|
return InterlockedIncrement(&ioq->msg_cnt);
|
|
|
}
|
|
|
|
|
|
static __inline LONG dec_msg_cnt(ioqueue_t *ioq)
|
|
|
{
|
|
|
+ //return --ioq->msg_cnt;
|
|
|
return InterlockedDecrement(&ioq->msg_cnt);
|
|
|
}
|
|
|
|
|
|
@@ -247,6 +253,7 @@ static __inline void del_handler_list(ioqueue_handle_context *handle_ctx, ioqueu
|
|
|
|
|
|
static void ioqueue_handle_context_free(ioqueue_handle_context *handle_ctx)
|
|
|
{
|
|
|
+ WLog_DBG(TAG, "free ioqueue handle context: %d", handle_ctx->type);
|
|
|
if (handle_ctx->type == HANDLE_TYPE_UDPSOCK
|
|
|
|| handle_ctx->type == HANDLE_TYPE_TCPSOCK
|
|
|
|| handle_ctx->type == HANDLE_TYPE_ACCEPTOR) {
|
|
|
@@ -270,19 +277,25 @@ static void ioqueue_handle_context_free(ioqueue_handle_context *handle_ctx)
|
|
|
}
|
|
|
del_handler_list(handle_ctx, handle_ctx->owner);
|
|
|
}
|
|
|
-
|
|
|
+//ioqueue_handle_context_dec_ref()
|
|
|
+//ioqueue_handle_context_inc_ref
|
|
|
IMPLEMENT_REF_COUNT_MT(ioqueue_handle_context, ioqueue_handle_context, pending_ios, ioqueue_handle_context_free)
|
|
|
|
|
|
static __inline LONG inc_pending_io(ioqueue_handle_context *handle_ctx)
|
|
|
{
|
|
|
- return inc_ref(ioqueue_handle_context, handle_ctx);
|
|
|
+ LONG l = inc_ref(ioqueue_handle_context, handle_ctx);
|
|
|
+ WLog_DBG(TAG, "increase pending io: %d, cnt:%ld", handle_ctx->type, l);
|
|
|
+ return l;
|
|
|
}
|
|
|
|
|
|
static __inline LONG dec_pending_io(ioqueue_handle_context *handle_ctx)
|
|
|
{
|
|
|
- return dec_ref(ioqueue_handle_context, handle_ctx);
|
|
|
+ LONG l = dec_ref(ioqueue_handle_context, handle_ctx);
|
|
|
+ WLog_DBG(TAG, "decrease pending io: %d, cnt:%ld", handle_ctx->type, l);
|
|
|
+ return 1;
|
|
|
}
|
|
|
|
|
|
+/*
|
|
|
static SOCKET new_socket()
|
|
|
{
|
|
|
SOCKET sock = WSASocket(AF_INET, SOCK_STREAM, IPPROTO_TCP,
|
|
|
@@ -292,6 +305,7 @@ static SOCKET new_socket()
|
|
|
}
|
|
|
return sock;
|
|
|
}
|
|
|
+*/
|
|
|
|
|
|
static void delete_socket(SOCKET sock)
|
|
|
{
|
|
|
@@ -312,9 +326,17 @@ TOOLKIT_API ioqueue_t *ioqueue_create()
|
|
|
if (!ioq->ep) {
|
|
|
goto on_error_0;
|
|
|
}
|
|
|
-
|
|
|
+ ioq->msg_fd = eventfd(0, EFD_CLOEXEC | EFD_SEMAPHORE);
|
|
|
+ if (ioq->msg_fd == -1) {
|
|
|
+ WLog_ERR(TAG, "create event fd failed: %d", errno);
|
|
|
+ ioq->msg_fd = 0;
|
|
|
+ goto on_error_1;
|
|
|
+ }
|
|
|
+ if (evtpoll_attach(ioq->ep, ioq->msg_fd) != 0) {
|
|
|
+ goto on_error_2;
|
|
|
+ }
|
|
|
if (timer_heap_create(&ioq->tm_queue) != 0) {
|
|
|
- goto on_error_3;
|
|
|
+ goto on_error_2;
|
|
|
}
|
|
|
spinlock_init(&ioq->tm_queue_lock);
|
|
|
spinlock_init(&ioq->connect_list_lock);
|
|
|
@@ -324,7 +346,9 @@ TOOLKIT_API ioqueue_t *ioqueue_create()
|
|
|
|
|
|
return ioq;
|
|
|
|
|
|
-on_error_3:
|
|
|
+on_error_2:
|
|
|
+ close(ioq->msg_fd);
|
|
|
+on_error_1:
|
|
|
evtpoll_destroy(ioq->ep);
|
|
|
on_error_0:
|
|
|
free(ioq);
|
|
|
@@ -337,6 +361,8 @@ TOOLKIT_API void ioqueue_destroy(ioqueue_t *ioq)
|
|
|
assert(ioqueue_handler_empty(ioq));
|
|
|
assert(ioqueue_msg_empty(ioq));
|
|
|
timer_queue_destroy(ioq->tm_queue);
|
|
|
+ evtpoll_detach(ioq->ep, ioq->msg_fd);
|
|
|
+ close(ioq->msg_fd);
|
|
|
evtpoll_destroy(ioq->ep);
|
|
|
free(ioq);
|
|
|
}
|
|
|
@@ -446,14 +472,18 @@ static int pre_dispatch_network(BOOL* ret, DWORD* dwBytesTransfer, ioqueue_overl
|
|
|
assert(((ioqueue_accept_overlapped_t*)io_ctx)->client == INVALID_SOCKET);
|
|
|
addrlen = sizeof(addr);
|
|
|
bzero(&addr, addrlen);
|
|
|
- conn_socket = accept(handle_ctx->u.sock, (struct sockaddr*) & addr, &addrlen);
|
|
|
+ conn_socket = _accept(handle_ctx->u.sock, (struct sockaddr*) & addr, &addrlen);
|
|
|
if (conn_socket == -1) {
|
|
|
WLog_ERR(TAG, "accept connect socket failed: %d", errno);
|
|
|
return -1;
|
|
|
}
|
|
|
WLog_INFO(TAG, "new connected socket fd(%d) arrived at listen socket: %d from %s:%d",
|
|
|
conn_socket, handle_ctx->u.sock, inet_ntoa(addr.sin_addr), ntohs(addr.sin_port));
|
|
|
-
|
|
|
+ if (make_fd_cloexec(conn_socket, 1)) {
|
|
|
+ WLog_ERR(TAG, "enable cloexec failed: %d", errno);
|
|
|
+ closesocket(conn_socket);
|
|
|
+ return -1;
|
|
|
+ }
|
|
|
((ioqueue_accept_overlapped_t*)io_ctx)->client = conn_socket;
|
|
|
if (ret) *ret = TRUE;
|
|
|
if (dwBytesTransfer) *dwBytesTransfer = 0;
|
|
|
@@ -492,7 +522,7 @@ static int pre_dispatch_network(BOOL* ret, DWORD* dwBytesTransfer, ioqueue_overl
|
|
|
nwrite = 0;
|
|
|
}
|
|
|
else {
|
|
|
- WLog_ERR(TAG, "write error: %s(%d)", strerror(errno), errno);
|
|
|
+ WLog_ERR(TAG, "write error: %d", errno);
|
|
|
}
|
|
|
break;
|
|
|
}
|
|
|
@@ -523,10 +553,7 @@ static int pre_dispatch_network(BOOL* ret, DWORD* dwBytesTransfer, ioqueue_overl
|
|
|
n = 0;
|
|
|
for (; n < overlapped->wsabuf.len;)
|
|
|
{
|
|
|
- do
|
|
|
- {
|
|
|
- nread = _recv(tcpsock->u.sock, overlapped->wsabuf.buf + n, overlapped->wsabuf.len - n, 0);
|
|
|
- } while (nread < 0 && errno == EINTR);
|
|
|
+ nread = _recv(tcpsock->u.sock, overlapped->wsabuf.buf + n, overlapped->wsabuf.len - n, 0);
|
|
|
if (nread > 0) {
|
|
|
n += nread;
|
|
|
continue;
|
|
|
@@ -539,7 +566,7 @@ static int pre_dispatch_network(BOOL* ret, DWORD* dwBytesTransfer, ioqueue_overl
|
|
|
nread = 0;
|
|
|
break;
|
|
|
} else {
|
|
|
- WLog_ERR(TAG, "read error: %s(%d)", strerror(errno), errno);
|
|
|
+ WLog_ERR(TAG, "read error: %d", errno);
|
|
|
break;
|
|
|
}
|
|
|
}
|
|
|
@@ -624,6 +651,8 @@ static void dispatch_network(BOOL ret, DWORD dwBytesTransfer, ioqueue_overlapped
|
|
|
ioqueue_sendn_overlapped_t *overlapped = (ioqueue_sendn_overlapped_t*)io_ctx;
|
|
|
overlapped->sended_bytes += dwBytesTransfer;
|
|
|
if (err == 0 && overlapped->sended_bytes < overlapped->total_bytes) {
|
|
|
+ int rc;
|
|
|
+ DWORD bytesWritten;
|
|
|
ioqueue_tcpsock_t* tcpsock = overlapped->base.handle_ctx;
|
|
|
overlapped->wsabuf.buf += dwBytesTransfer;
|
|
|
overlapped->wsabuf.len -= dwBytesTransfer;
|
|
|
@@ -634,7 +663,14 @@ static void dispatch_network(BOOL ret, DWORD dwBytesTransfer, ioqueue_overlapped
|
|
|
overlapped->base.ov.OffsetHigh = 0;
|
|
|
ioqueue_overlapped_set_mask(io_ctx, sizeof(ioqueue_sendn_overlapped_t));
|
|
|
WLog_WARN(TAG, "OV_SENDN: Must be due with this situation %d < %d", overlapped->sended_bytes, overlapped->total_bytes);
|
|
|
- evtpoll_subscribe(ioqueue_tcpsock_get_owned_ioqueue(tcpsock)->ep, EV_WRITE, tcpsock->u.sock, NULL, io_ctx);
|
|
|
+ //rc = _send(tcpsock->u.sock, overlapped->wsabuf.buf, overlapped->wsabuf.len, 0);
|
|
|
+ if (0 != evtpoll_subscribe(ioqueue_tcpsock_get_owned_ioqueue(tcpsock)->ep, EV_WRITE, tcpsock->u.sock, NULL, io_ctx)) {
|
|
|
+ dec_pending_io(handle_ctx);
|
|
|
+ overlapped->on_send_callback(handle_ctx, io_ctx, overlapped->original_buf,
|
|
|
+ overlapped->sended_bytes, base_ov->user_data, -1);
|
|
|
+ }
|
|
|
+ //rc = WSASend(handle_ctx->u.sock, &overlapped->wsabuf, 1, &bytesWritten,
|
|
|
+ // 0, &overlapped->base.ov, NULL);
|
|
|
//if (rc != 0 && WSAGetLastError() != WSA_IO_PENDING) {
|
|
|
// dec_pending_io(handle_ctx);
|
|
|
// overlapped->on_send_callback(handle_ctx, io_ctx, overlapped->original_buf,
|
|
|
@@ -642,7 +678,7 @@ static void dispatch_network(BOOL ret, DWORD dwBytesTransfer, ioqueue_overlapped
|
|
|
//}
|
|
|
} else {
|
|
|
ioqueue_tcpsock_t* tcpsock = overlapped->base.handle_ctx;
|
|
|
- evtpoll_unsubscribe(ioqueue_tcpsock_get_owned_ioqueue(tcpsock)->ep, EV_WRITE, tcpsock->u.sock, 0);
|
|
|
+ evtpoll_unsubscribe(ioqueue_tcpsock_get_owned_ioqueue(tcpsock)->ep, EV_WRITE, tcpsock->u.sock, 0, NULL, NULL);
|
|
|
overlapped->on_send_callback(handle_ctx, io_ctx, overlapped->original_buf,
|
|
|
overlapped->sended_bytes, base_ov->user_data, err);
|
|
|
}
|
|
|
@@ -831,36 +867,75 @@ static void dispatch_msg(ioqueue_t *ioq, int msg_type, param_size_t param1, para
|
|
|
|
|
|
TOOLKIT_API int ioqueue_post_message(ioqueue_t *ioq, int msg_type, param_size_t param1, param_size_t param2)
|
|
|
{
|
|
|
+
|
|
|
ioqueue_msg *msg;
|
|
|
+ uint64_t wdata = 0;
|
|
|
+ int rc;
|
|
|
+ WLog_DBG(TAG, "==> ioqueue post message: %d", msg_type);
|
|
|
assert(ioq);
|
|
|
msg = MALLOC_T(ioqueue_msg);
|
|
|
+ if (msg == NULL)
|
|
|
+ return -1;
|
|
|
+ ioqueue_overlapped_set_mask((ioqueue_overlapped_t*)(uintptr_t)(msg), sizeof(OVERLAPPED));
|
|
|
msg->msg_type = msg_type;
|
|
|
msg->param1 = param1;
|
|
|
msg->param2 = param2;
|
|
|
msg->evt = NULL;
|
|
|
+ WLog_DBG(TAG, "subscribe msg: 0x%08X", msg);
|
|
|
+ if (0 != evtpoll_subscribe(ioq->ep, EV_READ, ioq->msg_fd, msg, NULL)) {
|
|
|
+ WLog_ERR(TAG, "ioqueue subscribe msg eventfd failed.");
|
|
|
+ free(msg);
|
|
|
+ return -1;
|
|
|
+ }
|
|
|
inc_msg_cnt(ioq);
|
|
|
- if (!PostQueuedCompletionStatus(ioq->iocp, 0, (ULONG_PTR)msg, NULL)) {
|
|
|
+ wdata = 1;
|
|
|
+ do
|
|
|
+ {
|
|
|
+ rc = write(ioq->msg_fd, &wdata, sizeof wdata);
|
|
|
+ } while (rc < 0 && rc == EINTR);
|
|
|
+ if (rc == -1) {
|
|
|
+ WLog_ERR(TAG, "write to eventfd failed: %d", errno);
|
|
|
dec_msg_cnt(ioq);
|
|
|
free(msg);
|
|
|
return -1;
|
|
|
}
|
|
|
+ WLog_DBG(TAG, "<== ioqueue post message: %d", msg_type);
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
TOOLKIT_API int ioqueue_send_message(ioqueue_t *ioq, int msg_type, param_size_t param1, param_size_t param2)
|
|
|
{
|
|
|
- ioqueue_msg msg = {msg_type, param1, param2};
|
|
|
+ ioqueue_msg msg;
|
|
|
+ int rc;
|
|
|
+ uint64_t wdata = 0;
|
|
|
+ WLog_DBG(TAG, "==> ioqueue send message: %d", msg_type);
|
|
|
+ memset(&msg, 0, sizeof(ioqueue_msg));
|
|
|
+ msg.msg_type = msg_type;
|
|
|
+ msg.param1 = param1;
|
|
|
+ msg.param2 = param2;
|
|
|
+ ioqueue_overlapped_set_mask((ioqueue_overlapped_t*)(uintptr_t)(&msg), sizeof(OVERLAPPED));
|
|
|
assert(ioq);
|
|
|
+ if (0 != evtpoll_subscribe(ioq->ep, EV_READ, ioq->msg_fd, &msg, NULL)) {
|
|
|
+ WLog_ERR(TAG, "ioqueue subscribe msg eventfd failed.");
|
|
|
+ return -1;
|
|
|
+ }
|
|
|
msg.evt = CreateEventA(NULL, TRUE, FALSE, NULL);
|
|
|
inc_msg_cnt(ioq);
|
|
|
- if (!PostQueuedCompletionStatus(ioq->iocp, 0, (ULONG_PTR)&msg, NULL)) {
|
|
|
- CloseHandle(msg.evt);
|
|
|
+ wdata = 1;
|
|
|
+ do {
|
|
|
+ rc = write(ioq->msg_fd, &wdata, sizeof wdata);
|
|
|
+ } while (rc < 0 && rc == EINTR);
|
|
|
+ if (rc == -1) {
|
|
|
+ WLog_ERR(TAG, "write to eventfd failed: (%d)", errno);
|
|
|
dec_msg_cnt(ioq);
|
|
|
+ CloseHandle(msg.evt);
|
|
|
return -1;
|
|
|
}
|
|
|
+ WLog_DBG(TAG, "wait send message result: 0x%08X", &msg);
|
|
|
WaitForSingleObject(msg.evt, INFINITE);
|
|
|
CloseHandle(msg.evt);
|
|
|
dec_msg_cnt(ioq);
|
|
|
+ WLog_DBG(TAG, "<== ioqueue send message: %d", msg_type);
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
@@ -955,12 +1030,35 @@ TOOLKIT_API int ioqueue_poll(ioqueue_t* q, int timeout)
|
|
|
, pe->events & EPOLLOUT ? 1: 0 ,pe->events & EPOLLIN ? 1: 0);
|
|
|
|
|
|
while (n >= 0) {
|
|
|
- ioqueue_overlapped_t* io_ctx = NULL;
|
|
|
- n = evtpoll_deal(ioq->ep, pe, &io_ctx, 1);
|
|
|
+ LPOVERLAPPED iocp_pov = 0;
|
|
|
+ n = evtpoll_deal(ioq->ep, pe, &iocp_pov, 1);
|
|
|
if (!n) {
|
|
|
+ ioqueue_overlapped_t* io_ctx = (ioqueue_overlapped_t*)iocp_pov;
|
|
|
assert(io_ctx);
|
|
|
- pre_dispatch_network(&ret, &dwBytesTransfer, io_ctx);
|
|
|
- dispatch_network(ret, dwBytesTransfer, io_ctx);
|
|
|
+ if (ioqueue_overlapped_get_type(io_ctx) != EV_BUS_ENDPOINT) {
|
|
|
+ pre_dispatch_network(&ret, &dwBytesTransfer, io_ctx);
|
|
|
+ dispatch_network(ret, dwBytesTransfer, io_ctx);
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ WLog_DBG(TAG, "msg arrived.");
|
|
|
+ uint64_t rdata;
|
|
|
+ ioqueue_msg* msg = (ioqueue_msg*)iocp_pov;
|
|
|
+ int msg_type = msg->msg_type;
|
|
|
+ int param1 = msg->param1;
|
|
|
+ int param2 = msg->param2;
|
|
|
+ HANDLE evt = msg->evt;
|
|
|
+ do {
|
|
|
+ ret = read(ioq->msg_fd, &rdata, sizeof rdata);
|
|
|
+ } while (ret < 0 && errno == EINTR);
|
|
|
+ if (!evt)
|
|
|
+ free(msg);
|
|
|
+ if (ret < 0) {
|
|
|
+ WLog_ERR(TAG, "read msg fd failed: %d", errno);
|
|
|
+ abort();
|
|
|
+ }
|
|
|
+ dispatch_msg(ioq, msg_type, param1, param2, evt);
|
|
|
+ dec_msg_cnt(ioq);
|
|
|
+ }
|
|
|
t++;
|
|
|
count++;
|
|
|
}
|
|
|
@@ -1056,15 +1154,19 @@ TOOLKIT_API int ioqueue_acceptor_create(ioqueue_t *ioq,
|
|
|
/*Warning: only the front third params are effective !!*/
|
|
|
acceptor->u.sock = WSASocket(AF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, 0, WSA_FLAG_OVERLAPPED);
|
|
|
if (acceptor->u.sock == INVALID_SOCKET) {
|
|
|
- WLog_ERR(TAG, "accept socket create failed: %s", strerror(errno));
|
|
|
+ WLog_ERR(TAG, "accept socket create failed: %d", errno);
|
|
|
goto on_error;
|
|
|
}
|
|
|
nonblock_sock(acceptor->u.sock);
|
|
|
+ if (make_fd_cloexec(acceptor->u.sock, 1) != 0) {
|
|
|
+ WLog_ERR(TAG, "set accept socked fd cloexec failed: %d", errno);
|
|
|
+ goto on_error;
|
|
|
+ }
|
|
|
service.sin_family = AF_INET;
|
|
|
service.sin_port = htons(port);
|
|
|
service.sin_addr.s_addr = ip ? inet_addr(ip) : htonl(INADDR_ANY);
|
|
|
if (bind(acceptor->u.sock, (struct sockaddr*) & service, sizeof(struct sockaddr)) != 0) {
|
|
|
- WLog_ERR(TAG, "bind sockect %d failed: %s", acceptor->u.sock, strerror(errno));
|
|
|
+ WLog_ERR(TAG, "bind sockect %d failed: %d", acceptor->u.sock, (errno));
|
|
|
goto on_error;
|
|
|
}
|
|
|
if (evtpoll_attach(ioq->ep, acceptor->u.sock)) {
|
|
|
@@ -1095,16 +1197,42 @@ TOOLKIT_API int ioqueue_acceptor_listen(ioqueue_acceptor_t* acceptor, int backlo
|
|
|
TOOLKIT_API void ioqueue_acceptor_destroy(ioqueue_acceptor_t* acceptor)
|
|
|
{
|
|
|
assert(acceptor);
|
|
|
+ WLog_DBG(TAG, "destroy ioqueue acceptor.");
|
|
|
dec_ref(ioqueue_handle_context, acceptor);
|
|
|
}
|
|
|
|
|
|
TOOLKIT_API void ioqueue_acceptor_close(ioqueue_acceptor_t* acceptor)
|
|
|
{
|
|
|
+ WLog_DBG(TAG, "close ioqueue acceptor.");
|
|
|
SOCKET s;
|
|
|
assert(acceptor);
|
|
|
s = acceptor->u.sock;
|
|
|
if (s != INVALID_SOCKET) {
|
|
|
acceptor->u.sock = INVALID_SOCKET;
|
|
|
+ /*at Windows, IOCP would returned anything that make dec pending happen when close acceptor socket*/
|
|
|
+ /*we should let the poll thread to do this job!!!!!!*/
|
|
|
+ {
|
|
|
+ int rc;
|
|
|
+ void* io = NULL;
|
|
|
+ ioqueue_t* ioq = acceptor->owner;
|
|
|
+ assert(ioq);
|
|
|
+ rc = evtpoll_unsubscribe(ioq->ep, EV_ACCEPT, s, 0, &io, NULL);
|
|
|
+ if (rc == 0 && io != NULL) {
|
|
|
+ WLog_DBG(TAG, "cleaer pending state.");
|
|
|
+ ioqueue_overlapped_t* io_ctx = (ioqueue_overlapped_t*)io;
|
|
|
+ dispatch_network(FALSE, 0, io_ctx);
|
|
|
+
|
|
|
+ //ioqueue_accept_overlapped_t* overlapped = (ioqueue_accept_overlapped_t*)io;
|
|
|
+ //fastlock_enter(acceptor->ov_pending_list_lock);
|
|
|
+ //list_del(&overlapped->base.pending_entry);
|
|
|
+ //fastlock_leave(acceptor->ov_pending_list_lock);
|
|
|
+ //dec_pending_io(acceptor);
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ WLog_WARN(TAG, "unsubcribe failed: %d", rc);
|
|
|
+ }
|
|
|
+ evtpoll_detach(ioq->ep, s);
|
|
|
+ }
|
|
|
closesocket(s);
|
|
|
}
|
|
|
}
|
|
|
@@ -1172,7 +1300,7 @@ TOOLKIT_API int ioqueue_acceptor_accept(ioqueue_acceptor_t* acceptor, SOCKET *s,
|
|
|
if (FD_ISSET(acceptor->u.sock, &ex_set))
|
|
|
return -1;
|
|
|
if (FD_ISSET(acceptor->u.sock, &set)) {
|
|
|
- SOCKET fd = accept(acceptor->u.sock, addr, addrlen);
|
|
|
+ SOCKET fd = _accept(acceptor->u.sock, addr, addrlen);
|
|
|
if (fd != INVALID_SOCKET) {
|
|
|
*s = fd;
|
|
|
return 0;
|
|
|
@@ -1759,8 +1887,28 @@ TOOLKIT_API void ioqueue_tcpsock_close(ioqueue_tcpsock_t *tcpsock)
|
|
|
SOCKET s;
|
|
|
assert(tcpsock);
|
|
|
s = tcpsock->u.sock;
|
|
|
- if (s != INVALID_SOCKET) {
|
|
|
+ if (s != INVALID_SOCKET) { /*this condition maybe so important!!*/
|
|
|
tcpsock->u.sock = INVALID_SOCKET;
|
|
|
+ /*we should let the poll thread to do this job!!!!!!*/
|
|
|
+ {
|
|
|
+ int rc;
|
|
|
+ void* rdata = NULL;
|
|
|
+ void* wdata = NULL;
|
|
|
+ ioqueue_t* ioq = tcpsock->owner;
|
|
|
+ assert(ioq);
|
|
|
+ rc = evtpoll_unsubscribe(ioq->ep, EV_READ_WRITE_WITH_LT_PURE, s, 0, &rdata, &wdata);
|
|
|
+ if (rc == 0 && (rdata || wdata)) {
|
|
|
+ WLog_DBG(TAG, "clear tcpsocket state. r(0x%08X), w(0x%08X)", rdata, wdata);
|
|
|
+ if (rdata) {
|
|
|
+ ioqueue_overlapped_t* io_ctx = (ioqueue_overlapped_t*)rdata;
|
|
|
+ dispatch_network(FALSE, 0, io_ctx);
|
|
|
+ }
|
|
|
+ if (wdata) {
|
|
|
+ ioqueue_overlapped_t* io_ctx = (ioqueue_overlapped_t*)wdata;
|
|
|
+ dispatch_network(FALSE, 0, io_ctx);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
closesocket(s);
|
|
|
}
|
|
|
}
|