修复了线程池中BUG;修复了iocp及win32消息事件引擎的BUG

This commit is contained in:
zsxxsz 2014-02-21 23:01:57 +08:00
parent b20e0b6c53
commit 9a016e24b1
13 changed files with 146 additions and 58 deletions

View File

@ -42,7 +42,7 @@ endif
##############################################################################
.PHONY = check help all clean install uninstall uninstall_all build_bin build_src
VERSION = 3.0.11
VERSION = 3.0.17
help:
@(echo "usage: make help|all|clean|install|uninstall|uninstall_all|build_bin|build_src")

View File

@ -1,5 +1,6 @@
修改历史列表:
------------------------------------------------------------------------
67) 2014.2.21 --- acl 3.0.17 版本发布!(因线程池库存在严重 BUG所以发布此紧急版本)
66) 2014.2.17 --- acl 3.0.16 版本发布!
65) 2014.1.25 --- acl 3.0.15 版本发布!
64) 2014.1.11

View File

@ -1,5 +1,13 @@
修改历史列表:
------------------------------------------------------------------------
427) 2014.2.21
427.1) bugfix: events_wmsg.c 中在回调函数中没有将 stream 流针对传递,这会影响
基于 win32 消息事件的异步 IO 过程
427.2) bugfix: events_iocp.c 当主动关闭完成端口时,对于未决状态,不应提前释放
重叠结构对象(http://support.microsoft.com/kb/192800/zh-cn)
427.3) bugfix: acl_pthread_pool.c 线程条件变量链表的操作方法存在指针越界问题
------------------------------------------------------------------------
426) 2014.2.17

View File

@ -53,8 +53,8 @@ END
//
VS_VERSION_INFO VERSIONINFO
FILEVERSION 2,1,2,9
PRODUCTVERSION 2,1,2,9
FILEVERSION 3,0,1,7
PRODUCTVERSION 3,0,1,7
FILEFLAGSMASK 0x17L
#ifdef _DEBUG
FILEFLAGS 0x1L
@ -71,12 +71,12 @@ BEGIN
BEGIN
VALUE "Comments", "本库为跨平台的C库包括了网络通讯服务器框架等功能"
VALUE "FileDescription", "acl 库"
VALUE "FileVersion", "2, 1, 2, 9"
VALUE "FileVersion", "3, 0, 1, 7"
VALUE "InternalName", "lib_acl"
VALUE "LegalCopyright", "zsx (C) 2011"
VALUE "OriginalFilename", "lib_acl.lib"
VALUE "ProductName", " acl 库"
VALUE "ProductVersion", "2, 1, 2, 9"
VALUE "ProductVersion", "3, 0, l, 7"
END
END
BLOCK "VarFileInfo"

View File

@ -50,6 +50,8 @@ struct IOCP_EVENT {
int type;
#define IOCP_EVENT_READ (1 << 0)
#define IOCP_EVENT_WRITE (1 << 2)
#define IOCP_EVENT_DEAD (1 << 3)
ACL_EVENT_FDTABLE *fdp;
#define ACCEPT_ADDRESS_LENGTH ((sizeof(struct sockaddr_in) + 16))
@ -73,20 +75,44 @@ static void stream_on_close(ACL_VSTREAM *stream, void *arg)
}
/* 必须在释放 fdp->event_read/fdp->event_write 前关闭套接口句柄 */
if (ACL_VSTREAM_SOCK(stream) != ACL_SOCKET_INVALID && stream->close_fn)
shutdown(ACL_VSTREAM_SOCK(stream), 0);
shutdown(ACL_VSTREAM_SOCK(stream), 1);
if (ACL_VSTREAM_SOCK(stream) != ACL_SOCKET_INVALID
&& stream->close_fn)
{
(void) stream->close_fn(ACL_VSTREAM_SOCK(stream));
else if (ACL_VSTREAM_FILE(stream) != ACL_FILE_INVALID && stream->fclose_fn)
} else if (ACL_VSTREAM_FILE(stream) != ACL_FILE_INVALID
&& stream->fclose_fn)
{
(void) stream->fclose_fn(ACL_VSTREAM_FILE(stream));
}
ACL_VSTREAM_SOCK(stream) = ACL_SOCKET_INVALID;
ACL_VSTREAM_FILE(stream) = ACL_FILE_INVALID;
if (fdp->event_read) {
acl_myfree(fdp->event_read);
/* 如果完成端口处于未决状态,则不能释放重叠结构,需在主循环的
* GetQueuedCompletionStatus
*/
if (HasOverlappedIoCompleted(&fdp->event_read->overlapped))
acl_myfree(fdp->event_read);
else {
fdp->event_read->type = IOCP_EVENT_DEAD;
fdp->event_read->fdp = NULL;
}
fdp->event_read = NULL;
}
if (fdp->event_write) {
acl_myfree(fdp->event_write);
/* 如果完成端口处于未决状态,则不能释放重叠结构,需在主循环的
* GetQueuedCompletionStatus
*/
if (HasOverlappedIoCompleted(&fdp->event_write->overlapped))
acl_myfree(fdp->event_write);
else {
fdp->event_write->type = IOCP_EVENT_DEAD;
fdp->event_write->fdp = NULL;
}
fdp->event_write = NULL;
}
@ -741,42 +767,64 @@ TAG_DONE:
DWORD lastError = 0;
IOCP_EVENT *iocp_event = NULL;
isSuccess = GetQueuedCompletionStatus(ev->h_iocp, &bytesTransferred,
(DWORD*) &fdp, (OVERLAPPED**) &iocp_event, delay);
isSuccess = GetQueuedCompletionStatus(ev->h_iocp,
&bytesTransferred, (DWORD*) &fdp,
(OVERLAPPED**) &iocp_event, delay);
if (!isSuccess) {
if (iocp_event == NULL)
break;
if (!(fdp->event_type & (ACL_EVENT_XCPT | ACL_EVENT_RW_TIMEOUT))) {
if (iocp_event->type == IOCP_EVENT_DEAD)
acl_myfree(iocp_event);
else if (iocp_event->fdp == NULL) {
acl_msg_warn("%s(%d): fdp null",
myname, __LINE__);
acl_myfree(iocp_event);
} else if (iocp_event->fdp != fdp)
acl_msg_fatal("%s(%d): invalid fdp",
myname, __LINE__);
else if (!(fdp->event_type & (ACL_EVENT_XCPT
| ACL_EVENT_RW_TIMEOUT)))
{
fdp->event_type |= ACL_EVENT_XCPT;
fdp->fdidx_ready = eventp->fdcnt_ready;
eventp->fdtabs_ready[eventp->fdcnt_ready++] = fdp;
eventp->fdtabs_ready[eventp->fdcnt_ready] = fdp;
eventp->fdcnt_ready++;
}
continue;
}
acl_assert(fdp == iocp_event->fdp);
if ((fdp->event_type & (ACL_EVENT_XCPT | ACL_EVENT_RW_TIMEOUT)))
if ((fdp->event_type & (ACL_EVENT_XCPT
| ACL_EVENT_RW_TIMEOUT)))
{
continue;
}
if (iocp_event->type == IOCP_EVENT_READ) {
acl_assert(fdp->event_read == iocp_event);
iocp_event->type &= ~IOCP_EVENT_READ;
fdp->stream->sys_read_ready = 1;
if ((fdp->event_type & (ACL_EVENT_READ | ACL_EVENT_WRITE)) == 0)
if ((fdp->event_type & (ACL_EVENT_READ
| ACL_EVENT_WRITE)) == 0)
{
fdp->event_type |= ACL_EVENT_READ;
fdp->fdidx_ready = eventp->fdcnt_ready;
eventp->fdtabs_ready[eventp->fdcnt_ready++] = fdp;
eventp->fdtabs_ready[eventp->fdcnt_ready] = fdp;
eventp->fdcnt_ready++;
}
}
if (iocp_event->type == IOCP_EVENT_WRITE) {
acl_assert(fdp->event_write == iocp_event);
iocp_event->type &= ~IOCP_EVENT_WRITE;
if ((fdp->event_type & (ACL_EVENT_READ | ACL_EVENT_WRITE)) == 0)
if ((fdp->event_type & (ACL_EVENT_READ
| ACL_EVENT_WRITE)) == 0)
{
fdp->event_type |= ACL_EVENT_WRITE;
fdp->fdidx_ready = eventp->fdcnt_ready;
eventp->fdtabs_ready[eventp->fdcnt_ready++] = fdp;
eventp->fdtabs_ready[eventp->fdcnt_ready] = fdp;
eventp->fdcnt_ready++;
}
}
delay = 0;

View File

@ -481,10 +481,10 @@ static void handleClose(EVENT_WMSG *ev, ACL_SOCKET sockfd)
return;
else if (fdp->r_callback)
fdp->r_callback(ACL_EVENT_XCPT, &ev->event,
NULL, fdp->r_context);
fdp->stream, fdp->r_context);
else if (fdp->w_callback)
fdp->w_callback(ACL_EVENT_XCPT, &ev->event,
NULL, fdp->w_context);
fdp->stream, fdp->w_context);
/*
else
acl_msg_error("%s(%d): w_callback and r_callback null"
@ -506,7 +506,7 @@ static void handleConnect(EVENT_WMSG *ev, ACL_SOCKET sockfd)
else {
fdp->stream->flag &= ~ACL_VSTREAM_FLAG_CONNECTING;
fdp->w_callback(ACL_EVENT_WRITE, &ev->event,
NULL, fdp->w_context);
fdp->stream, fdp->w_context);
}
}
@ -520,7 +520,8 @@ static void handleAccept(EVENT_WMSG *ev, ACL_SOCKET sockfd)
else if (fdp->r_callback == NULL)
acl_msg_fatal("%s(%d): fdp callback null", myname, __LINE__);
fdp->r_callback(ACL_EVENT_READ, &ev->event, NULL, fdp->r_context);
fdp->r_callback(ACL_EVENT_READ, &ev->event,
fdp->stream, fdp->r_context);
}
static void handleRead(EVENT_WMSG *ev, ACL_SOCKET sockfd)
@ -532,15 +533,15 @@ static void handleRead(EVENT_WMSG *ev, ACL_SOCKET sockfd)
acl_msg_error("%s(%d): fdp null for sockfd(%d)",
myname, __LINE__, (int) sockfd);
else if ((fdp->stream->type & ACL_VSTREAM_TYPE_LISTEN))
fdp->r_callback(ACL_EVENT_READ, &ev->event, NULL,
fdp->r_context);
fdp->r_callback(ACL_EVENT_READ, &ev->event,
fdp->stream, fdp->r_context);
else if (fdp->r_callback != NULL) {
/* 该描述字可读则设置 ACL_VSTREAM 的系统可读标志从而触发
* ACL_VSTREAM read
*/
fdp->stream->sys_read_ready = 1;
fdp->r_callback(ACL_EVENT_READ, &ev->event,
NULL, fdp->r_context);
fdp->stream, fdp->r_context);
}
/* else
acl_msg_error("%s(%d): fdp->r_callback null for sockfd(%d)",
@ -560,7 +561,7 @@ static void handleWrite(EVENT_WMSG *ev, ACL_SOCKET sockfd)
handleConnect(ev, sockfd);
else if (fdp->w_callback != NULL)
fdp->w_callback(ACL_EVENT_WRITE, &ev->event,
NULL, fdp->w_context);
fdp->stream, fdp->w_context);
/*
else
acl_msg_error("%s(%d): fdp->w_callback null for sockfd(%d)",

View File

@ -24,7 +24,7 @@
#include "init.h"
static char *version = "lib_acl_3.0.16";
static char *version = "lib_acl_3.0.17";
const char *acl_version(void)
{

View File

@ -83,7 +83,6 @@ struct acl_pthread_pool_t {
thread_worker *thr_first; /* first idle thread */
thread_worker *thr_iter; /* for bat operation */
thread_cond *cond_first;
thread_cond *cond_last;
int poller_running; /* is poller thread running ? */
int qlen; /* the work queue's length */
int job_nslot;
@ -193,7 +192,7 @@ static thread_cond *thread_cond_create(void)
thread_cond *cond = (thread_cond*)
acl_mycalloc(1, sizeof(thread_cond));
acl_pthread_cond_init(&cond->cond, NULL);
acl_assert(acl_pthread_cond_init(&cond->cond, NULL) == 0);
return cond;
}
@ -207,7 +206,6 @@ static thread_worker *worker_create(acl_pthread_pool_t *thr_pool)
{
thread_worker *thr = (thread_worker*) acl_mycalloc(1,
sizeof(thread_worker));
thread_cond *cond = thr_pool->cond_first;
thr->id = (unsigned long) acl_pthread_self();
thr->idle = thr_pool->idle_timeout;
@ -222,27 +220,20 @@ static thread_worker *worker_create(acl_pthread_pool_t *thr_pool)
} else
thr->idle = 0;
if (cond == NULL) {
cond = thread_cond_create();
acl_assert(acl_pthread_cond_init(&cond->cond, NULL) == 0);
} else {
thr_pool->cond_first = cond->next;
if (thr_pool->cond_last == cond)
thr_pool->cond_last = NULL;
}
if (thr_pool->cond_first != NULL) {
thr->cond = thr_pool->cond_first;
thr_pool->cond_first = thr_pool->cond_first->next;
} else
thr->cond = thread_cond_create();
thr->cond = cond;
thr->mutex = &thr_pool->worker_mutex;
return thr;
}
static void worker_free(acl_pthread_pool_t *thr_pool, thread_worker *thr)
{
if (thr_pool->cond_first == NULL)
thr_pool->cond_first = thr->cond;
else
thr_pool->cond_last->next = thr->cond;
thr_pool->cond_last = thr->cond;
thr->cond->next = thr_pool->cond_first;
thr_pool->cond_first = thr->cond;
acl_myfree(thr);
}
@ -431,19 +422,18 @@ static void *worker_thread(void* arg)
}
}
thr = worker_create(thr_pool);
acl_assert(thr->mutex == &thr_pool->worker_mutex);
mutex = thr->mutex;
/* lock the thread pool's global mutex at first */
status = acl_pthread_mutex_lock(mutex);
status = acl_pthread_mutex_lock(&thr_pool->worker_mutex);
if (status != 0) {
SET_ERRNO(status);
acl_msg_fatal("%s(%d), %s: lock failed: %s", __FILE__,
__LINE__, myname, acl_last_serror());
}
thr = worker_create(thr_pool);
mutex = thr->mutex;
for (;;) {
/* handle thread self's job first */
@ -498,7 +488,7 @@ static void *worker_thread(void* arg)
status = acl_pthread_mutex_unlock(mutex);
if (status != 0) {
SET_ERRNO(status);
acl_msg_error("%s, %s(%d): unlock error(%s)",
acl_msg_fatal("%s, %s(%d): unlock error(%s)",
__FILE__, myname, __LINE__, acl_last_serror());
}
@ -943,7 +933,6 @@ static void thread_pool_init(acl_pthread_pool_t *thr_pool)
thr_pool->schedule_warn = 100;
thr_pool->schedule_wait = 100;
thr_pool->cond_first = NULL;
thr_pool->cond_last = NULL;
}
/* create work queue */

View File

@ -195,8 +195,8 @@ public:
*/
bool timeout_callback()
{
std::cout << "Timeout ..." << std::endl;
return (true);
std::cout << "Timeout, delete it ..." << std::endl;
return (false);
}
private:
@ -239,7 +239,7 @@ public:
client->add_timeout_callback(callback);
// 从异步流读一行数据
client->gets(10, false);
client->gets(3, false);
return (true);
}
};
@ -251,7 +251,7 @@ static void usage(const char* procname)
int main(int argc, char* argv[])
{
bool use_kernel = true;
bool use_kernel = false;
int ch;
while ((ch = getopt(argc, argv, "hk")) > 0)

View File

@ -194,6 +194,12 @@
<Culture>0x0804</Culture>
<AdditionalIncludeDirectories>$(IntDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ResourceCompile>
<PostBuildEvent>
<Command>copy ..\..\..\dist\lib\win32\lib_acl_d.dll $(OutDir) /Y
copy ..\..\..\dist\lib\win32\lib_acl_cpp_d.dll $(OutDir) /Y
copy ..\..\..\dist\lib\win32\lib_protocol_d.dll $(OutDir) /Y
</Command>
</PostBuildEvent>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Releasedll|Win32'">
<ClCompile>
@ -226,8 +232,10 @@
<AdditionalIncludeDirectories>$(IntDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ResourceCompile>
<PostBuildEvent>
<Command>
</Command>
<Command>copy ..\..\..\dist\lib\win32\lib_acl.dll $(OutDir) /Y
copy ..\..\..\dist\lib\win32\lib_acl_cpp.dll $(OutDir) /Y
copy ..\..\..\dist\lib\win32\lib_protocol.dll $(OutDir) /Y
</Command>
</PostBuildEvent>
</ItemDefinitionGroup>
<ItemGroup>

View File

@ -0,0 +1,2 @@
include ../Makefile.in
PROG = thread_pool_client

View File

@ -0,0 +1,28 @@
#include <getopt.h>
#include "lib_acl.h"
static void thread_run(void *arg)
{
(void) arg;
}
int main(void)
{
int nthreads = 200, count = 100, i;
acl_pthread_pool_t *thrpool;
thrpool = acl_thread_pool_create(nthreads, 1);
for (i = 0; i < nthreads; i++)
acl_pthread_pool_add(thrpool, thread_run, &count);
sleep(2);
for (i = 0; i < nthreads; i++)
acl_pthread_pool_add(thrpool, thread_run, &count);
printf("enter any key to exit\r\n");
getchar();
acl_pthread_pool_destroy(thrpool);
return 0;
}

View File

@ -0,0 +1,3 @@
#!/bin/sh
valgrind --tool=memcheck --leak-check=yes -v ./thread_pool_client