1
0
mirror of https://github.com/libuv/libuv synced 2025-03-28 21:13:16 +00:00

Add ol_close_cb stack test and fix it for Windows

This commit is contained in:
Bert Belder 2011-04-05 04:24:03 +02:00
parent 56608452af
commit 4899328166
6 changed files with 60 additions and 14 deletions

View File

@ -22,6 +22,7 @@
</ItemGroup>
<ItemGroup>
<ClCompile Include="test\echo-server.c" />
<ClCompile Include="test\test-callback-stack.c" />
<ClCompile Include="test\test-fail-always.c" />
<ClCompile Include="test\test-pass-always.c" />
<ClCompile Include="test\test-ping-pong.c" />

View File

@ -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) {
ol_req *req;
if (handle->_.flags & OL_HANDLE_CLOSING)
return 0;
handle->_.error = e;
@ -293,17 +296,21 @@ int ol_close_error(ol_handle* handle, ol_err e) {
switch (handle->type) {
case OL_TCP:
closesocket(handle->_.socket);
if (handle->_.reqs_pending != 0) {
/* Cannot free the handle right now because there are queued */
/* operations. Close the socket, wait for for all packets to come */
/* out, then have ol_poll call close_cb. */
handle->_.flags |= OL_HANDLE_CLOSING;
} else {
/* There are no pending operations. Call the close callback now. */
handle->_.flags |= OL_HANDLE_CLOSED;
if (handle->close_cb)
handle->close_cb(handle, e);
if (handle->_.reqs_pending == 0) {
/* If there are no operations queued for this socket, queue one */
/* manually, so ol_poll will call close_cb. */
req = (ol_req*)malloc(sizeof(*req));
req->handle = handle;
req->type = OL_CLOSE;
req->_.flags = 0;
if (!PostQueuedCompletionStatus(ol_iocp_, 0, (ULONG_PTR)handle, &req->_.overlapped))
ol_fatal_error(GetLastError(), "PostQueuedCompletionStatus");
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;
default:
@ -588,7 +595,6 @@ void ol_poll() {
handle->_.flags |= OL_HANDLE_CLOSED;
if (handle->close_cb)
handle->close_cb(handle, handle->_.error);
ol_refs_--;
}
return;
}
@ -649,6 +655,10 @@ void ol_poll() {
free(req);
}
return;
case OL_CLOSE:
/* Should never get here */
assert(0);
}
}

View File

@ -28,5 +28,4 @@ typedef struct {
unsigned int flags;
unsigned int reqs_pending;
ol_err error;
} ol_handle_private;
} ol_handle_private;

3
ol.h
View File

@ -52,7 +52,8 @@ typedef enum {
OL_ACCEPT,
OL_READ,
OL_WRITE,
OL_SHUTDOWN
OL_SHUTDOWN,
OL_CLOSE
} ol_req_type;

View 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;
}

View File

@ -1,5 +1,6 @@
TEST_DECLARE (echo_server)
TEST_DECLARE (ping_pong)
TEST_DECLARE (close_cb_stack);
TEST_DECLARE (pass_always)
TEST_DECLARE (fail_always)
@ -7,6 +8,8 @@ TEST_LIST_START
TEST_ENTRY (ping_pong)
TEST_HELPER (ping_pong, echo_server)
TEST_ENTRY (close_cb_stack)
TEST_ENTRY (fail_always)
TEST_ENTRY (pass_always)