Add ol_close_cb stack test and fix it for Windows
This commit is contained in:
parent
56608452af
commit
4899328166
@ -22,6 +22,7 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClCompile Include="test\echo-server.c" />
|
<ClCompile Include="test\echo-server.c" />
|
||||||
|
<ClCompile Include="test\test-callback-stack.c" />
|
||||||
<ClCompile Include="test\test-fail-always.c" />
|
<ClCompile Include="test\test-fail-always.c" />
|
||||||
<ClCompile Include="test\test-pass-always.c" />
|
<ClCompile Include="test\test-pass-always.c" />
|
||||||
<ClCompile Include="test\test-ping-pong.c" />
|
<ClCompile Include="test\test-ping-pong.c" />
|
||||||
|
|||||||
32
ol-win.c
32
ol-win.c
@ -285,7 +285,10 @@ ol_handle* ol_tcp_handle_new(ol_close_cb close_cb, void* data) {
|
|||||||
|
|
||||||
|
|
||||||
int ol_close_error(ol_handle* handle, ol_err e) {
|
int ol_close_error(ol_handle* handle, ol_err e) {
|
||||||
|
ol_req *req;
|
||||||
|
|
||||||
if (handle->_.flags & OL_HANDLE_CLOSING)
|
if (handle->_.flags & OL_HANDLE_CLOSING)
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
handle->_.error = e;
|
handle->_.error = e;
|
||||||
@ -293,17 +296,21 @@ int ol_close_error(ol_handle* handle, ol_err e) {
|
|||||||
switch (handle->type) {
|
switch (handle->type) {
|
||||||
case OL_TCP:
|
case OL_TCP:
|
||||||
closesocket(handle->_.socket);
|
closesocket(handle->_.socket);
|
||||||
if (handle->_.reqs_pending != 0) {
|
if (handle->_.reqs_pending == 0) {
|
||||||
/* Cannot free the handle right now because there are queued */
|
/* If there are no operations queued for this socket, queue one */
|
||||||
/* operations. Close the socket, wait for for all packets to come */
|
/* manually, so ol_poll will call close_cb. */
|
||||||
/* out, then have ol_poll call close_cb. */
|
req = (ol_req*)malloc(sizeof(*req));
|
||||||
handle->_.flags |= OL_HANDLE_CLOSING;
|
req->handle = handle;
|
||||||
} else {
|
req->type = OL_CLOSE;
|
||||||
/* There are no pending operations. Call the close callback now. */
|
req->_.flags = 0;
|
||||||
handle->_.flags |= OL_HANDLE_CLOSED;
|
if (!PostQueuedCompletionStatus(ol_iocp_, 0, (ULONG_PTR)handle, &req->_.overlapped))
|
||||||
if (handle->close_cb)
|
ol_fatal_error(GetLastError(), "PostQueuedCompletionStatus");
|
||||||
handle->close_cb(handle, e);
|
req->_.flags |= OL_REQ_PENDING;
|
||||||
|
handle->_.reqs_pending++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* After all packets to come out, ol_poll will call close_cb. */
|
||||||
|
handle->_.flags |= OL_HANDLE_CLOSING;
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@ -588,7 +595,6 @@ void ol_poll() {
|
|||||||
handle->_.flags |= OL_HANDLE_CLOSED;
|
handle->_.flags |= OL_HANDLE_CLOSED;
|
||||||
if (handle->close_cb)
|
if (handle->close_cb)
|
||||||
handle->close_cb(handle, handle->_.error);
|
handle->close_cb(handle, handle->_.error);
|
||||||
ol_refs_--;
|
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -649,6 +655,10 @@ void ol_poll() {
|
|||||||
free(req);
|
free(req);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
case OL_CLOSE:
|
||||||
|
/* Should never get here */
|
||||||
|
assert(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
1
ol-win.h
1
ol-win.h
@ -29,4 +29,3 @@ typedef struct {
|
|||||||
unsigned int reqs_pending;
|
unsigned int reqs_pending;
|
||||||
ol_err error;
|
ol_err error;
|
||||||
} ol_handle_private;
|
} ol_handle_private;
|
||||||
|
|
||||||
|
|||||||
3
ol.h
3
ol.h
@ -52,7 +52,8 @@ typedef enum {
|
|||||||
OL_ACCEPT,
|
OL_ACCEPT,
|
||||||
OL_READ,
|
OL_READ,
|
||||||
OL_WRITE,
|
OL_WRITE,
|
||||||
OL_SHUTDOWN
|
OL_SHUTDOWN,
|
||||||
|
OL_CLOSE
|
||||||
} ol_req_type;
|
} ol_req_type;
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
32
test/test-callback-stack.c
Normal file
32
test/test-callback-stack.c
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
#include "../ol.h"
|
||||||
|
#include "test.h"
|
||||||
|
|
||||||
|
|
||||||
|
int nested = 0;
|
||||||
|
int close_cb_called = 0;
|
||||||
|
|
||||||
|
|
||||||
|
void close_cb(ol_handle *handle, ol_err e) {
|
||||||
|
assert("ol_close error" && e == 0);
|
||||||
|
assert("ol_close_cb not called from a fresh stack" && nested == 0);
|
||||||
|
close_cb_called++;
|
||||||
|
ol_free(handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
TEST_IMPL(close_cb_stack) {
|
||||||
|
ol_handle *handle;
|
||||||
|
|
||||||
|
ol_init();
|
||||||
|
handle = ol_tcp_handle_new(&close_cb, NULL);
|
||||||
|
|
||||||
|
nested++;
|
||||||
|
ol_close(handle);
|
||||||
|
nested--;
|
||||||
|
|
||||||
|
ol_run();
|
||||||
|
|
||||||
|
assert("ol_close_cb not called exactly once" && close_cb_called);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
@ -1,5 +1,6 @@
|
|||||||
TEST_DECLARE (echo_server)
|
TEST_DECLARE (echo_server)
|
||||||
TEST_DECLARE (ping_pong)
|
TEST_DECLARE (ping_pong)
|
||||||
|
TEST_DECLARE (close_cb_stack);
|
||||||
TEST_DECLARE (pass_always)
|
TEST_DECLARE (pass_always)
|
||||||
TEST_DECLARE (fail_always)
|
TEST_DECLARE (fail_always)
|
||||||
|
|
||||||
@ -7,6 +8,8 @@ TEST_LIST_START
|
|||||||
TEST_ENTRY (ping_pong)
|
TEST_ENTRY (ping_pong)
|
||||||
TEST_HELPER (ping_pong, echo_server)
|
TEST_HELPER (ping_pong, echo_server)
|
||||||
|
|
||||||
|
TEST_ENTRY (close_cb_stack)
|
||||||
|
|
||||||
TEST_ENTRY (fail_always)
|
TEST_ENTRY (fail_always)
|
||||||
|
|
||||||
TEST_ENTRY (pass_always)
|
TEST_ENTRY (pass_always)
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user