Skip to content

Commit

Permalink
add iocp crash mock test (to reproduce the issue #985)
Browse files Browse the repository at this point in the history
  • Loading branch information
jimying committed Nov 23, 2024
1 parent c239fc8 commit a56a07b
Show file tree
Hide file tree
Showing 4 changed files with 164 additions and 1 deletion.
2 changes: 1 addition & 1 deletion pjlib/build/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ export TEST_OBJS += activesock.o atomic.o echo_clt.o errno.o exception.o \
select.o sleep.o sock.o sock_perf.o ssl_sock.o \
string.o test.o thread.o timer.o timestamp.o \
udp_echo_srv_sync.o udp_echo_srv_ioqueue.o \
unittest_test.o util.o
unittest_test.o util.o ioq_iocp_crash_test.o
export TEST_CFLAGS += $(_CFLAGS)
export TEST_CXXFLAGS += $(_CXXFLAGS)
export TEST_LDFLAGS += $(PJLIB_LDLIB) $(_LDFLAGS)
Expand Down
157 changes: 157 additions & 0 deletions pjlib/src/pjlib-test/ioq_iocp_crash_test.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
/**
* ioqueue iocp crash reproduce test (issue #985)
*/
#include <pjlib.h>
#include "test.h"

#define THIS_FILE "ioq_iocp_crash_test.c"

struct sock_info_t {
pj_activesock_t *asock;
pj_sockaddr bound_addr;
pj_pool_t *pool;
};

struct iocp_test_t {
pj_pool_t *pool;
pj_ioqueue_t *ioq;
pj_thread_t *tid;
pj_bool_t quit;
struct sock_info_t *socks[8];
pj_activesock_t *asock_send;
};


static int worker_thread(void *p)
{
struct iocp_test_t *test = (struct iocp_test_t *)p;

while(!test->quit) {
pj_time_val timeout = {0, 10};
pj_ioqueue_poll(test->ioq, &timeout);
}

return 0;
}

static pj_bool_t on_data_recvfrom(pj_activesock_t *asock,
void *data,
pj_size_t size,
const pj_sockaddr_t *src_addr,
int addr_len,
pj_status_t status)
{
(void)asock;
(void)src_addr;
(void)addr_len;
PJ_LOG(3, (THIS_FILE, "on_data_recvfrom() data:%.*s, status:%d", (int)size, (char *)data, status));
return PJ_TRUE;
}

int ioqueue_iocp_crash_test(void)
{
struct iocp_test_t *test;
pj_pool_t *pool;
pj_status_t status;
unsigned i;
pj_activesock_cfg cfg;
pj_activesock_cb cb;
struct sock_info_t *sock_info;
pj_sockaddr loc_addr;
pj_str_t loop = {"127.0.0.1", 9};

if (strcmp(pj_ioqueue_name(), "iocp")) {
/* ignore if ioqueue framework is not iocp */
return PJ_SUCCESS;
}

pool = pj_pool_create(mem, "iocp-crash-test", 1000, 1000, NULL);
test = PJ_POOL_ZALLOC_T(pool, struct iocp_test_t);
test->pool = pool;
status = pj_ioqueue_create(pool, PJ_IOQUEUE_MAX_HANDLES, &test->ioq);
if (status != PJ_SUCCESS) {
status = -900;
goto on_error;
}

status = pj_thread_create(pool, "iocp-crash-test", worker_thread, test, 0, 0, &test->tid);
if (status != PJ_SUCCESS) {
status = -901;
goto on_error;
}

pj_activesock_cfg_default(&cfg);
pj_bzero(&cb, sizeof(cb));
cb.on_data_recvfrom = on_data_recvfrom;

/* create send socket */
status = pj_activesock_create_udp(pool, NULL, &cfg, test->ioq, &cb, NULL, &test->asock_send, NULL);
if (status != PJ_SUCCESS) {
status = -902;
goto on_error;
}

/* create sockets to recevie */
pj_sockaddr_init(pj_AF_INET(), &loc_addr, &loop, 0);
for (i = 0; i < PJ_ARRAY_SIZE(test->socks); i++) {
pool = pj_pool_create(mem, "sock%p", 1000, 1000, NULL);
sock_info = PJ_POOL_ZALLOC_T(pool, struct sock_info_t);
sock_info->pool = pool;

status = pj_activesock_create_udp(pool, &loc_addr, &cfg, test->ioq, &cb, NULL, &sock_info->asock, &sock_info->bound_addr);
if (status != PJ_SUCCESS) {
status = -903;
pj_pool_release(pool);
goto on_error;
}
test->socks[i] = sock_info;
pj_activesock_start_recvfrom(sock_info->asock, pool, 2000, 0);
}

for (i = 0; i < PJ_ARRAY_SIZE(test->socks); i++) {
pj_ioqueue_op_key_t *send_key;
pj_str_t data;
pj_ssize_t sent;
pj_pool_t *pool = test->pool;

sock_info = test->socks[i];
send_key = PJ_POOL_ZALLOC_T(pool, pj_ioqueue_op_key_t);
pj_strdup2_with_null(pool, &data, "hello");
sent = data.slen;
status = pj_activesock_sendto(test->asock_send, send_key, data.ptr, &sent, 0,
&sock_info->bound_addr,
pj_sockaddr_get_len(&sock_info->bound_addr));
if (status != PJ_SUCCESS && status != PJ_EPENDING) {
char buf[80];
pj_sockaddr_print(&sock_info->bound_addr, buf, sizeof(buf), 3);
PJ_PERROR(2, (THIS_FILE, status, "send error, dest:%s", buf));
}
}

pj_thread_sleep(20);
for (i = 0; i < PJ_ARRAY_SIZE(test->socks); i++) {
sock_info = test->socks[i];
pj_activesock_close(sock_info->asock);
pj_pool_release(sock_info->pool);
test->socks[i] = NULL;
}

pj_thread_sleep(20);
test->quit = PJ_TRUE;
status = PJ_SUCCESS;

on_error:
if (test->tid)
pj_thread_join(test->tid);
for (i = 0; i < PJ_ARRAY_SIZE(test->socks); i++) {
sock_info = test->socks[i];
if (!sock_info)
break;
pj_activesock_close(sock_info->asock);
pj_pool_release(sock_info->pool);
}
if (test->ioq)
pj_ioqueue_destroy(test->ioq);
pj_pool_release(test->pool);
return status;
}
4 changes: 4 additions & 0 deletions pjlib/src/pjlib-test/test.c
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,10 @@ int test_inner(void)
param_echo_port);
#endif

#if INCLUDE_IOCP_CRASH_TEST
DO_TEST( ioqueue_iocp_crash_test() );
#endif

goto on_return;

on_return:
Expand Down
2 changes: 2 additions & 0 deletions pjlib/src/pjlib-test/test.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
# define WITH_BENCHMARK 1
#endif

#define INCLUDE_IOCP_CRASH_TEST !TEST_DEFAULT
#define INCLUDE_ERRNO_TEST GROUP_LIBC
#define INCLUDE_TIMESTAMP_TEST GROUP_OS
#define INCLUDE_EXCEPTION_TEST GROUP_LIBC
Expand Down Expand Up @@ -109,6 +110,7 @@ extern int select_test(void);
extern int udp_ioqueue_test(void);
extern int udp_ioqueue_unreg_test(void);
extern int tcp_ioqueue_test(void);
extern int ioqueue_iocp_crash_test(void);
extern int ioqueue_perf_test(void);
extern int ioqueue_stress_test(void);
extern int activesock_test(void);
Expand Down

0 comments on commit a56a07b

Please sign in to comment.