]> granicus.if.org Git - libevent/commitdiff
Refactor IOCP callback interface
authorNick Mathewson <nickm@torproject.org>
Mon, 2 Nov 2009 19:51:26 +0000 (19:51 +0000)
committerNick Mathewson <nickm@torproject.org>
Mon, 2 Nov 2009 19:51:26 +0000 (19:51 +0000)
Chris Davis points out that GetQueuedCompletionStatus
sometimes returns false not to report "No events for
you!" but instead to report "An overlapped operation
failed."  Add a way to tell an event_overlapped that
its operation failed.

svn:r1490

buffer_iocp.c
event_iocp.c
iocp-internal.h
listener.c

index 5071a9db45584cb785142bb4a238eca6992dfc50..b52f84d6893ebee7bc7845edf88f91fe9b92ef43 100644 (file)
@@ -111,7 +111,7 @@ pin_release(struct event_overlapped *eo, unsigned flag)
 
 /** IOCP callback invoked when a read operation is finished. */
 static void
-read_completed(struct event_overlapped *eo, uintptr_t _, ev_ssize_t nBytes)
+read_completed(struct event_overlapped *eo, uintptr_t _, ev_ssize_t nBytes, int ok)
 {
        struct buffer_overlapped *buf_o = upcast_overlapped(eo);
        struct evbuffer_overlapped *buf = buf_o->buf;
@@ -120,6 +120,8 @@ read_completed(struct event_overlapped *eo, uintptr_t _, ev_ssize_t nBytes)
        struct evbuffer_iovec iov[2];
        int n_vec;
 
+       // XXXX use ok
+
        EVBUFFER_LOCK(evbuf, EVTHREAD_WRITE);
        buf->read_in_progress = 0;
        evbuffer_unfreeze(evbuf, 0);
@@ -145,8 +147,9 @@ read_completed(struct event_overlapped *eo, uintptr_t _, ev_ssize_t nBytes)
 
 /** IOCP callback invoked when a write operation is finished. */
 static void
-write_completed(struct event_overlapped *eo, uintptr_t _, ev_ssize_t nBytes)
+write_completed(struct event_overlapped *eo, uintptr_t _, ev_ssize_t nBytes, int ok)
 {
+       // XXX use ok
        struct buffer_overlapped *buf_o = upcast_overlapped(eo);
        struct evbuffer_overlapped *buf = buf_o->buf;
 
index b4350ef63955e1209e0dc418c0732ca2df676ec4..9cce605b7bc69cd878c1aee4807c704e1dff95f5 100644 (file)
@@ -47,28 +47,29 @@ event_overlapped_init(struct event_overlapped *o, iocp_callback cb)
 }
 
 static void
-handle_entry(OVERLAPPED *o, ULONG_PTR completion_key, DWORD nBytes)
+handle_entry(OVERLAPPED *o, ULONG_PTR completion_key, DWORD nBytes, int ok)
 {
        struct event_overlapped *eo =
            EVUTIL_UPCAST(o, struct event_overlapped, overlapped);
-       eo->cb(eo, completion_key, nBytes);
+       eo->cb(eo, completion_key, nBytes, ok);
 }
 
 static void
 loop(void *_port)
 {
        struct event_iocp_port *port = _port;
-       OVERLAPPED *overlapped;
-       ULONG_PTR key;
-       DWORD bytes;
        long ms = port->ms;
        HANDLE p = port->port;
 
        if (ms <= 0)
                ms = INFINITE;
 
-       while (GetQueuedCompletionStatus(p, &bytes, &key,
-               &overlapped, ms)) {
+       while (1) {
+               OVERLAPPED *overlapped=NULL;
+               ULONG_PTR key=0;
+               DWORD bytes=0;
+               int ok = GetQueuedCompletionStatus(p, &bytes, &key,
+                       &overlapped, ms);
                EnterCriticalSection(&port->lock);
                if (port->shutdown) {
                        if (--port->n_live_threads == 0)
@@ -78,8 +79,10 @@ loop(void *_port)
                }
                LeaveCriticalSection(&port->lock);
 
-               if (key != NOTIFICATION_KEY)
-                       handle_entry(overlapped, key, bytes);
+               if (key != NOTIFICATION_KEY && overlapped)
+                       handle_entry(overlapped, key, bytes, ok);
+               else if (!overlapped)
+                       break;
        }
        event_warnx("GetQueuedCompletionStatus exited with no event.");
        EnterCriticalSection(&port->lock);
index 31024cc10ee34d852c74d2fbc23ecbd07e874ade..18b89d25962b01245a8ca3e201f6140328c28ca7 100644 (file)
@@ -34,7 +34,7 @@ extern "C" {
 struct event_overlapped;
 struct event_iocp_port;
 struct evbuffer;
-typedef void (*iocp_callback)(struct event_overlapped *, uintptr_t, ev_ssize_t);
+typedef void (*iocp_callback)(struct event_overlapped *, uintptr_t, ev_ssize_t, int success);
 
 /* This whole file is actually win32 only. We wrap the structures in a win32
  * ifdef so that we can test-compile code that uses these interfaces on
index 8cdaef566d212cb745545003c0436b2313126db1..e14062543c6b269c2074a6ffdaefc67ae4c7a73a 100644 (file)
@@ -297,7 +297,7 @@ struct accepting_socket {
 };
 
 static void accepted_socket_cb(struct event_overlapped *o, uintptr_t key,
-    ev_ssize_t n);
+    ev_ssize_t n, int ok);
 
 static struct accepting_socket *
 new_accepting_socket(struct evconnlistener_iocp *lev, int family)
@@ -370,7 +370,7 @@ start_accepting(struct accepting_socket *as)
                as->buflen/2, as->buflen/2,
                &pending, &as->overlapped.overlapped)) {
                /* Immediate success! */
-               accepted_socket_cb(&as->overlapped, 1, 0);
+               accepted_socket_cb(&as->overlapped, 1, 0, 1);
                result = 0;
        } else {
                int err = WSAGetLastError();
@@ -395,10 +395,11 @@ stop_accepting(struct accepting_socket *as)
 #endif
 
 static void
-accepted_socket_cb(struct event_overlapped *o, uintptr_t key, ev_ssize_t n)
+accepted_socket_cb(struct event_overlapped *o, uintptr_t key, ev_ssize_t n, int ok)
 {
        /* Run this whole thing deferred unless some MT flag is set */
        /* XXX needs locking. */
+       /* XXX use ok */
 
        struct sockaddr *sa_local=NULL, *sa_remote=NULL;
        int socklen_local=0, socklen_remote=0;