server: Store async list in process object and use that to find async in cansel_async request.
Signed-off-by: Jacek Caban <jacek@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
d1064669f4
commit
055918c982
|
@ -31,12 +31,15 @@
|
||||||
#include "object.h"
|
#include "object.h"
|
||||||
#include "file.h"
|
#include "file.h"
|
||||||
#include "request.h"
|
#include "request.h"
|
||||||
|
#include "process.h"
|
||||||
|
#include "handle.h"
|
||||||
|
|
||||||
struct async
|
struct async
|
||||||
{
|
{
|
||||||
struct object obj; /* object header */
|
struct object obj; /* object header */
|
||||||
struct thread *thread; /* owning thread */
|
struct thread *thread; /* owning thread */
|
||||||
struct list queue_entry; /* entry in async queue list */
|
struct list queue_entry; /* entry in async queue list */
|
||||||
|
struct list process_entry; /* entry in process list */
|
||||||
struct async_queue *queue; /* queue containing this async */
|
struct async_queue *queue; /* queue containing this async */
|
||||||
unsigned int status; /* current status */
|
unsigned int status; /* current status */
|
||||||
struct timeout_user *timeout;
|
struct timeout_user *timeout;
|
||||||
|
@ -132,6 +135,7 @@ static void async_destroy( struct object *obj )
|
||||||
struct async *async = (struct async *)obj;
|
struct async *async = (struct async *)obj;
|
||||||
assert( obj->ops == &async_ops );
|
assert( obj->ops == &async_ops );
|
||||||
|
|
||||||
|
list_remove( &async->process_entry );
|
||||||
list_remove( &async->queue_entry );
|
list_remove( &async->queue_entry );
|
||||||
async_reselect( async );
|
async_reselect( async );
|
||||||
|
|
||||||
|
@ -244,6 +248,7 @@ struct async *create_async( struct thread *thread, struct async_queue *queue, co
|
||||||
async->signaled = 0;
|
async->signaled = 0;
|
||||||
|
|
||||||
list_add_tail( &queue->queue, &async->queue_entry );
|
list_add_tail( &queue->queue, &async->queue_entry );
|
||||||
|
list_add_tail( &thread->process->asyncs, &async->process_entry );
|
||||||
grab_object( async );
|
grab_object( async );
|
||||||
|
|
||||||
if (queue->fd) set_fd_signaled( queue->fd, 0 );
|
if (queue->fd) set_fd_signaled( queue->fd, 0 );
|
||||||
|
@ -343,23 +348,22 @@ int async_waiting( struct async_queue *queue )
|
||||||
return async->status == STATUS_PENDING;
|
return async->status == STATUS_PENDING;
|
||||||
}
|
}
|
||||||
|
|
||||||
int async_wake_up_by( struct async_queue *queue, struct process *process,
|
static int cancel_async( struct process *process, struct object *obj, struct thread *thread, client_ptr_t iosb )
|
||||||
struct thread *thread, client_ptr_t iosb, unsigned int status )
|
|
||||||
{
|
{
|
||||||
struct list *ptr, *next;
|
struct async *async;
|
||||||
int woken = 0;
|
int woken = 0;
|
||||||
|
|
||||||
if (!queue || (!process && !thread && !iosb)) return 0;
|
restart:
|
||||||
|
LIST_FOR_EACH_ENTRY( async, &process->asyncs, struct async, process_entry )
|
||||||
LIST_FOR_EACH_SAFE( ptr, next, &queue->queue )
|
|
||||||
{
|
{
|
||||||
struct async *async = LIST_ENTRY( ptr, struct async, queue_entry );
|
if (async->status == STATUS_CANCELLED) continue;
|
||||||
if ( (!process || async->thread->process == process) &&
|
if ((!obj || (async->queue->fd && get_fd_user( async->queue->fd ) == obj)) &&
|
||||||
(!thread || async->thread == thread) &&
|
(!thread || async->thread == thread) &&
|
||||||
(!iosb || async->data.iosb == iosb) )
|
(!iosb || async->data.iosb == iosb))
|
||||||
{
|
{
|
||||||
async_terminate( async, status );
|
async_terminate( async, STATUS_CANCELLED );
|
||||||
woken++;
|
woken++;
|
||||||
|
goto restart;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return woken;
|
return woken;
|
||||||
|
@ -379,3 +383,17 @@ void async_wake_up( struct async_queue *queue, unsigned int status )
|
||||||
if (status == STATUS_ALERTED) break; /* only wake up the first one */
|
if (status == STATUS_ALERTED) break; /* only wake up the first one */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* cancels all async I/O */
|
||||||
|
DECL_HANDLER(cancel_async)
|
||||||
|
{
|
||||||
|
struct object *obj = get_handle_obj( current->process, req->handle, 0, NULL );
|
||||||
|
struct thread *thread = req->only_thread ? current : NULL;
|
||||||
|
|
||||||
|
if (obj)
|
||||||
|
{
|
||||||
|
int count = cancel_async( current->process, obj, thread, req->iosb );
|
||||||
|
if (!count && req->iosb) set_error( STATUS_NOT_FOUND );
|
||||||
|
release_object( obj );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
21
server/fd.c
21
server/fd.c
|
@ -2118,12 +2118,7 @@ void default_fd_reselect_async( struct fd *fd, struct async_queue *queue )
|
||||||
/* default cancel_async() fd routine */
|
/* default cancel_async() fd routine */
|
||||||
int default_fd_cancel_async( struct fd *fd, struct process *process, struct thread *thread, client_ptr_t iosb )
|
int default_fd_cancel_async( struct fd *fd, struct process *process, struct thread *thread, client_ptr_t iosb )
|
||||||
{
|
{
|
||||||
int n = 0;
|
return 0;
|
||||||
|
|
||||||
n += async_wake_up_by( fd->read_q, process, thread, iosb, STATUS_CANCELLED );
|
|
||||||
n += async_wake_up_by( fd->write_q, process, thread, iosb, STATUS_CANCELLED );
|
|
||||||
n += async_wake_up_by( fd->wait_q, process, thread, iosb, STATUS_CANCELLED );
|
|
||||||
return n;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int is_valid_mounted_device( struct stat *st )
|
static inline int is_valid_mounted_device( struct stat *st )
|
||||||
|
@ -2519,20 +2514,6 @@ DECL_HANDLER(register_async)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* cancels all async I/O */
|
|
||||||
DECL_HANDLER(cancel_async)
|
|
||||||
{
|
|
||||||
struct fd *fd = get_handle_fd_obj( current->process, req->handle, 0 );
|
|
||||||
struct thread *thread = req->only_thread ? current : NULL;
|
|
||||||
|
|
||||||
if (fd)
|
|
||||||
{
|
|
||||||
int count = fd->fd_ops->cancel_async( fd, current->process, thread, req->iosb );
|
|
||||||
if (!count && req->iosb) set_error( STATUS_NOT_FOUND );
|
|
||||||
release_object( fd );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* attach completion object to a fd */
|
/* attach completion object to a fd */
|
||||||
DECL_HANDLER(set_completion_info)
|
DECL_HANDLER(set_completion_info)
|
||||||
{
|
{
|
||||||
|
|
|
@ -175,8 +175,6 @@ extern void async_set_result( struct object *obj, unsigned int status,
|
||||||
extern int async_queued( struct async_queue *queue );
|
extern int async_queued( struct async_queue *queue );
|
||||||
extern int async_waiting( struct async_queue *queue );
|
extern int async_waiting( struct async_queue *queue );
|
||||||
extern void async_terminate( struct async *async, unsigned int status );
|
extern void async_terminate( struct async *async, unsigned int status );
|
||||||
extern int async_wake_up_by( struct async_queue *queue, struct process *process,
|
|
||||||
struct thread *thread, client_ptr_t iosb, unsigned int status );
|
|
||||||
extern void async_wake_up( struct async_queue *queue, unsigned int status );
|
extern void async_wake_up( struct async_queue *queue, unsigned int status );
|
||||||
extern struct completion *fd_get_completion( struct fd *fd, apc_param_t *p_key );
|
extern struct completion *fd_get_completion( struct fd *fd, apc_param_t *p_key );
|
||||||
extern void fd_copy_completion( struct fd *src, struct fd *dst );
|
extern void fd_copy_completion( struct fd *src, struct fd *dst );
|
||||||
|
|
|
@ -535,6 +535,7 @@ struct thread *create_process( int fd, struct thread *parent_thread, int inherit
|
||||||
process->rawinput_kbd = NULL;
|
process->rawinput_kbd = NULL;
|
||||||
list_init( &process->thread_list );
|
list_init( &process->thread_list );
|
||||||
list_init( &process->locks );
|
list_init( &process->locks );
|
||||||
|
list_init( &process->asyncs );
|
||||||
list_init( &process->classes );
|
list_init( &process->classes );
|
||||||
list_init( &process->dlls );
|
list_init( &process->dlls );
|
||||||
list_init( &process->rawinput_devices );
|
list_init( &process->rawinput_devices );
|
||||||
|
@ -614,6 +615,7 @@ static void process_destroy( struct object *obj )
|
||||||
|
|
||||||
/* we can't have a thread remaining */
|
/* we can't have a thread remaining */
|
||||||
assert( list_empty( &process->thread_list ));
|
assert( list_empty( &process->thread_list ));
|
||||||
|
assert( list_empty( &process->asyncs ));
|
||||||
|
|
||||||
assert( !process->sigkill_timeout ); /* timeout should hold a reference to the process */
|
assert( !process->sigkill_timeout ); /* timeout should hold a reference to the process */
|
||||||
|
|
||||||
|
|
|
@ -78,6 +78,7 @@ struct process
|
||||||
unsigned int is_terminating:1;/* is process terminating? */
|
unsigned int is_terminating:1;/* is process terminating? */
|
||||||
struct job *job; /* job object ascoicated with this process */
|
struct job *job; /* job object ascoicated with this process */
|
||||||
struct list job_entry; /* list entry for job object */
|
struct list job_entry; /* list entry for job object */
|
||||||
|
struct list asyncs; /* list of async object owned by the process */
|
||||||
struct list locks; /* list of file locks owned by the process */
|
struct list locks; /* list of file locks owned by the process */
|
||||||
struct list classes; /* window classes owned by the process */
|
struct list classes; /* window classes owned by the process */
|
||||||
struct console_input*console; /* console input */
|
struct console_input*console; /* console input */
|
||||||
|
|
|
@ -132,7 +132,6 @@ static enum server_fd_type sock_get_fd_type( struct fd *fd );
|
||||||
static obj_handle_t sock_ioctl( struct fd *fd, ioctl_code_t code, const async_data_t *async, int blocking );
|
static obj_handle_t sock_ioctl( struct fd *fd, ioctl_code_t code, const async_data_t *async, int blocking );
|
||||||
static void sock_queue_async( struct fd *fd, const async_data_t *data, int type, int count );
|
static void sock_queue_async( struct fd *fd, const async_data_t *data, int type, int count );
|
||||||
static void sock_reselect_async( struct fd *fd, struct async_queue *queue );
|
static void sock_reselect_async( struct fd *fd, struct async_queue *queue );
|
||||||
static int sock_cancel_async( struct fd *fd, struct process *process, struct thread *thread, client_ptr_t iosb );
|
|
||||||
|
|
||||||
static int sock_get_ntstatus( int err );
|
static int sock_get_ntstatus( int err );
|
||||||
static int sock_get_error( int err );
|
static int sock_get_error( int err );
|
||||||
|
@ -171,7 +170,7 @@ static const struct fd_ops sock_fd_ops =
|
||||||
sock_ioctl, /* ioctl */
|
sock_ioctl, /* ioctl */
|
||||||
sock_queue_async, /* queue_async */
|
sock_queue_async, /* queue_async */
|
||||||
sock_reselect_async, /* reselect_async */
|
sock_reselect_async, /* reselect_async */
|
||||||
sock_cancel_async /* cancel_async */
|
default_fd_cancel_async /* cancel_async */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -611,19 +610,6 @@ static void sock_reselect_async( struct fd *fd, struct async_queue *queue )
|
||||||
sock_reselect( sock );
|
sock_reselect( sock );
|
||||||
}
|
}
|
||||||
|
|
||||||
static int sock_cancel_async( struct fd *fd, struct process *process, struct thread *thread, client_ptr_t iosb )
|
|
||||||
{
|
|
||||||
struct sock *sock = get_fd_user( fd );
|
|
||||||
int n = 0;
|
|
||||||
|
|
||||||
assert( sock->obj.ops == &sock_ops );
|
|
||||||
|
|
||||||
n += async_wake_up_by( sock->read_q, process, thread, iosb, STATUS_CANCELLED );
|
|
||||||
n += async_wake_up_by( sock->write_q, process, thread, iosb, STATUS_CANCELLED );
|
|
||||||
n += async_wake_up_by( sock->ifchange_q, process, thread, iosb, STATUS_CANCELLED );
|
|
||||||
return n;
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct fd *sock_get_fd( struct object *obj )
|
static struct fd *sock_get_fd( struct object *obj )
|
||||||
{
|
{
|
||||||
struct sock *sock = (struct sock *)obj;
|
struct sock *sock = (struct sock *)obj;
|
||||||
|
|
Loading…
Reference in New Issue