server: Use a callback to free the accept_req structure.

Signed-off-by: Zebediah Figura <z.figura12@gmail.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Zebediah Figura 2021-02-08 17:40:42 -06:00 committed by Alexandre Julliard
parent 12783dabbc
commit 61abc500f5
3 changed files with 30 additions and 12 deletions

View File

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

View File

@ -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 );

View File

@ -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 )
{
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 );