Zebediah Figura : server: Use a callback to free the accept_req structure.

Alexandre Julliard julliard at winehq.org
Wed Feb 10 15:34:02 CST 2021


Module: wine
Branch: master
Commit: 61abc500f557cbd5f732688963843dc2d238c9e2
URL:    https://source.winehq.org/git/wine.git/?a=commit;h=61abc500f557cbd5f732688963843dc2d238c9e2

Author: Zebediah Figura <z.figura12 at gmail.com>
Date:   Mon Feb  8 17:40:42 2021 -0600

server: Use a callback to free the accept_req structure.

Signed-off-by: Zebediah Figura <z.figura12 at gmail.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 server/async.c | 15 +++++++++++++++
 server/file.h  |  4 ++++
 server/sock.c  | 23 +++++++++++------------
 3 files changed, 30 insertions(+), 12 deletions(-)

diff --git a/server/async.c b/server/async.c
index 6da61fd502c..1ac5117edb9 100644
--- a/server/async.c
+++ b/server/async.c
@@ -55,6 +55,8 @@ struct async
     struct completion   *completion;      /* completion associated with fd */
     apc_param_t          comp_key;        /* completion key associated with fd */
     unsigned int         comp_flags;      /* completion flags */
+    async_completion_callback completion_callback; /* callback to be called on completion */
+    void                *completion_callback_private; /* argument to completion_callback */
 };
 
 static void async_dump( struct object *obj, int verbose );
@@ -247,6 +249,8 @@ struct async *create_async( struct fd *fd, struct thread *thread, const async_da
     async->direct_result = 0;
     async->completion    = fd_get_completion( fd, &async->comp_key );
     async->comp_flags    = 0;
+    async->completion_callback = NULL;
+    async->completion_callback_private = NULL;
 
     if (iosb) async->iosb = (struct iosb *)grab_object( iosb );
     else async->iosb = NULL;
@@ -362,6 +366,13 @@ void async_set_timeout( struct async *async, timeout_t timeout, unsigned int sta
     async->timeout_status = status;
 }
 
+/* set a callback to be notified when the async is completed */
+void async_set_completion_callback( struct async *async, async_completion_callback func, void *private )
+{
+    async->completion_callback = func;
+    async->completion_callback_private = private;
+}
+
 static void add_async_completion( struct async *async, apc_param_t cvalue, unsigned int status,
                                   apc_param_t information )
 {
@@ -420,6 +431,10 @@ void async_set_result( struct object *obj, unsigned int status, apc_param_t tota
             async->signaled = 1;
             wake_up( &async->obj, 0 );
         }
+
+        if (async->completion_callback)
+            async->completion_callback( async->completion_callback_private );
+        async->completion_callback = NULL;
     }
 }
 
diff --git a/server/file.h b/server/file.h
index b41a6c3f0c4..3b70799a3ec 100644
--- a/server/file.h
+++ b/server/file.h
@@ -212,6 +212,9 @@ extern int is_serial_fd( struct fd *fd );
 extern struct object *create_serial( struct fd *fd );
 
 /* async I/O functions */
+
+typedef void (*async_completion_callback)( void *private );
+
 extern void free_async_queue( struct async_queue *queue );
 extern struct async *create_async( struct fd *fd, struct thread *thread, const async_data_t *data, struct iosb *iosb );
 extern struct async *create_request_async( struct fd *fd, unsigned int comp_flags, const async_data_t *data );
@@ -219,6 +222,7 @@ extern obj_handle_t async_handoff( struct async *async, int success, data_size_t
 extern void queue_async( struct async_queue *queue, struct async *async );
 extern void async_set_timeout( struct async *async, timeout_t timeout, unsigned int status );
 extern void async_set_result( struct object *obj, unsigned int status, apc_param_t total );
+extern void async_set_completion_callback( struct async *async, async_completion_callback func, void *private );
 extern void set_async_pending( struct async *async, int signal );
 extern int async_waiting( struct async_queue *queue );
 extern void async_terminate( struct async *async, unsigned int status );
diff --git a/server/sock.c b/server/sock.c
index 78b1578113b..3aed5494612 100644
--- a/server/sock.c
+++ b/server/sock.c
@@ -449,8 +449,9 @@ static inline int sock_error( struct fd *fd )
     return optval;
 }
 
-static void free_accept_req( struct accept_req *req )
+static void free_accept_req( void *private )
 {
+    struct accept_req *req = private;
     list_remove( &req->entry );
     if (req->acceptsock)
     {
@@ -582,7 +583,7 @@ static int sock_dispatch_asyncs( struct sock *sock, int event, int error )
 
         LIST_FOR_EACH_ENTRY( req, &sock->accept_list, struct accept_req, entry )
         {
-            if (!req->accepted)
+            if (req->iosb->status == STATUS_PENDING && !req->accepted)
             {
                 complete_async_accept( sock, req );
                 if (get_error() != STATUS_PENDING)
@@ -591,7 +592,7 @@ static int sock_dispatch_asyncs( struct sock *sock, int event, int error )
             }
         }
 
-        if (sock->accept_recv_req)
+        if (sock->accept_recv_req && sock->accept_recv_req->iosb->status == STATUS_PENDING)
         {
             complete_async_accept_recv( sock->accept_recv_req );
             if (get_error() != STATUS_PENDING)
@@ -626,9 +627,12 @@ static int sock_dispatch_asyncs( struct sock *sock, int event, int error )
             async_wake_up( &sock->write_q, status );
 
         LIST_FOR_EACH_ENTRY_SAFE( req, next, &sock->accept_list, struct accept_req, entry )
-            async_terminate( req->async, status );
+        {
+            if (req->iosb->status == STATUS_PENDING)
+                async_terminate( req->async, status );
+        }
 
-        if (sock->accept_recv_req)
+        if (sock->accept_recv_req && sock->accept_recv_req->iosb->status == STATUS_PENDING)
             async_terminate( sock->accept_recv_req->async, status );
     }
 
@@ -872,13 +876,6 @@ static void sock_queue_async( struct fd *fd, struct async *async, int type, int
 static void sock_reselect_async( struct fd *fd, struct async_queue *queue )
 {
     struct sock *sock = get_fd_user( fd );
-    struct accept_req *req, *next;
-
-    LIST_FOR_EACH_ENTRY_SAFE( req, next, &sock->accept_list, struct accept_req, entry )
-    {
-        if (req->iosb->status != STATUS_PENDING)
-            free_accept_req( req );
-    }
 
     /* ignore reselect on ifchange queue */
     if (&sock->ifchange_q != queue)
@@ -1434,6 +1431,7 @@ static int sock_ioctl( struct fd *fd, ioctl_code_t code, struct async *async )
             if (!(req = alloc_accept_req( sock, NULL, async, NULL ))) return 0;
             list_add_tail( &sock->accept_list, &req->entry );
 
+            async_set_completion_callback( async, free_accept_req, req );
             queue_async( &sock->accept_q, async );
             sock_reselect( sock );
             set_error( STATUS_PENDING );
@@ -1490,6 +1488,7 @@ static int sock_ioctl( struct fd *fd, ioctl_code_t code, struct async *async )
         release_object( acceptsock );
 
         acceptsock->wparam = params->accept_handle;
+        async_set_completion_callback( async, free_accept_req, req );
         queue_async( &sock->accept_q, async );
         sock_reselect( sock );
         set_error( STATUS_PENDING );




More information about the wine-cvs mailing list