mirror of
https://gitlab.winehq.org/wine/wine.git
synced 2024-11-21 17:09:06 -07:00
server: Preallocate wait handle in create_request_async and return it in read request.
alloc_handle is failable and when we're returning the handle, handling error properly is not really possible. Signed-off-by: Jacek Caban <jacek@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
e0760ce933
commit
0fb6099b01
5 changed files with 52 additions and 31 deletions
|
@ -48,6 +48,7 @@ struct async
|
|||
struct event *event;
|
||||
async_data_t data; /* data for async I/O call */
|
||||
struct iosb *iosb; /* I/O status block */
|
||||
obj_handle_t wait_handle; /* pre-allocated wait handle */
|
||||
};
|
||||
|
||||
static void async_dump( struct object *obj, int verbose );
|
||||
|
@ -262,6 +263,7 @@ struct async *create_async( struct thread *thread, const async_data_t *data, str
|
|||
async->timeout = NULL;
|
||||
async->queue = NULL;
|
||||
async->signaled = 0;
|
||||
async->wait_handle = 0;
|
||||
|
||||
if (iosb) async->iosb = (struct iosb *)grab_object( iosb );
|
||||
else async->iosb = NULL;
|
||||
|
@ -272,7 +274,8 @@ struct async *create_async( struct thread *thread, const async_data_t *data, str
|
|||
return async;
|
||||
}
|
||||
|
||||
/* create an async associated with iosb for async-based requests */
|
||||
/* create an async associated with iosb for async-based requests
|
||||
* returned async must be passed to async_handoff */
|
||||
struct async *create_request_async( struct thread *thread, const async_data_t *data )
|
||||
{
|
||||
struct async *async;
|
||||
|
@ -283,9 +286,39 @@ struct async *create_request_async( struct thread *thread, const async_data_t *d
|
|||
|
||||
async = create_async( current, data, iosb );
|
||||
release_object( iosb );
|
||||
if (async)
|
||||
{
|
||||
if (!(async->wait_handle = alloc_handle( current->process, async, SYNCHRONIZE, 0 )))
|
||||
{
|
||||
release_object( async );
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
return async;
|
||||
}
|
||||
|
||||
/* return async object status and wait handle to client */
|
||||
obj_handle_t async_handoff( struct async *async, int success )
|
||||
{
|
||||
obj_handle_t handle;
|
||||
if (!success)
|
||||
{
|
||||
close_handle( async->thread->process, async->wait_handle );
|
||||
async->wait_handle = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (async->iosb->status == STATUS_PENDING && !async_is_blocking( async ))
|
||||
{
|
||||
close_handle( async->thread->process, async->wait_handle);
|
||||
async->wait_handle = 0;
|
||||
}
|
||||
handle = async->wait_handle;
|
||||
async->wait_handle = 0;
|
||||
set_error( STATUS_PENDING );
|
||||
return handle;
|
||||
}
|
||||
|
||||
/* set the timeout of an async operation */
|
||||
void async_set_timeout( struct async *async, timeout_t timeout, unsigned int status )
|
||||
{
|
||||
|
|
|
@ -174,7 +174,7 @@ static struct fd *device_file_get_fd( struct object *obj );
|
|||
static int device_file_close_handle( struct object *obj, struct process *process, obj_handle_t handle );
|
||||
static void device_file_destroy( struct object *obj );
|
||||
static enum server_fd_type device_file_get_fd_type( struct fd *fd );
|
||||
static obj_handle_t device_file_read( struct fd *fd, struct async *async, file_pos_t pos );
|
||||
static int device_file_read( struct fd *fd, struct async *async, file_pos_t pos );
|
||||
static obj_handle_t device_file_write( struct fd *fd, struct async *async, file_pos_t pos );
|
||||
static obj_handle_t device_file_flush( struct fd *fd, struct async *async );
|
||||
static obj_handle_t device_file_ioctl( struct fd *fd, ioctl_code_t code, struct async *async );
|
||||
|
@ -462,15 +462,16 @@ static void set_file_user_ptr( struct device_file *file, client_ptr_t ptr )
|
|||
}
|
||||
|
||||
/* queue an irp to the device */
|
||||
static obj_handle_t queue_irp( struct device_file *file, struct irp_call *irp, struct async *async )
|
||||
static obj_handle_t queue_irp( struct device_file *file, struct irp_call *irp, struct async *async, int need_handle )
|
||||
{
|
||||
obj_handle_t handle = 0;
|
||||
|
||||
if (async_is_blocking( async ) && !(handle = alloc_handle( current->process, async, SYNCHRONIZE, 0 ))) return 0;
|
||||
if (!need_handle) handle = 1;
|
||||
else if (async_is_blocking( async ) && !(handle = alloc_handle( current->process, async, SYNCHRONIZE, 0 ))) return 0;
|
||||
|
||||
if (!fd_queue_async( file->fd, async, ASYNC_TYPE_WAIT ))
|
||||
{
|
||||
if (handle) close_handle( current->process, handle );
|
||||
if (need_handle && handle) close_handle( current->process, handle );
|
||||
return 0;
|
||||
}
|
||||
irp->async = (struct async *)grab_object( async );
|
||||
|
@ -484,7 +485,7 @@ static enum server_fd_type device_file_get_fd_type( struct fd *fd )
|
|||
return FD_TYPE_DEVICE;
|
||||
}
|
||||
|
||||
static obj_handle_t device_file_read( struct fd *fd, struct async *async, file_pos_t pos )
|
||||
static int device_file_read( struct fd *fd, struct async *async, file_pos_t pos )
|
||||
{
|
||||
struct device_file *file = get_fd_user( fd );
|
||||
struct irp_call *irp;
|
||||
|
@ -500,7 +501,7 @@ static obj_handle_t device_file_read( struct fd *fd, struct async *async, file_p
|
|||
irp = create_irp( file, ¶ms, async );
|
||||
if (!irp) return 0;
|
||||
|
||||
handle = queue_irp( file, irp, async );
|
||||
handle = queue_irp( file, irp, async, 0 );
|
||||
release_object( irp );
|
||||
return handle;
|
||||
}
|
||||
|
@ -521,7 +522,7 @@ static obj_handle_t device_file_write( struct fd *fd, struct async *async, file_
|
|||
irp = create_irp( file, ¶ms, async );
|
||||
if (!irp) return 0;
|
||||
|
||||
handle = queue_irp( file, irp, async );
|
||||
handle = queue_irp( file, irp, async, 1 );
|
||||
release_object( irp );
|
||||
return handle;
|
||||
}
|
||||
|
@ -540,7 +541,7 @@ static obj_handle_t device_file_flush( struct fd *fd, struct async *async )
|
|||
irp = create_irp( file, ¶ms, NULL );
|
||||
if (!irp) return 0;
|
||||
|
||||
handle = queue_irp( file, irp, async );
|
||||
handle = queue_irp( file, irp, async, 1 );
|
||||
release_object( irp );
|
||||
return handle;
|
||||
}
|
||||
|
@ -560,7 +561,7 @@ static obj_handle_t device_file_ioctl( struct fd *fd, ioctl_code_t code, struct
|
|||
irp = create_irp( file, ¶ms, async );
|
||||
if (!irp) return 0;
|
||||
|
||||
handle = queue_irp( file, irp, async );
|
||||
handle = queue_irp( file, irp, async, 1 );
|
||||
release_object( irp );
|
||||
return handle;
|
||||
}
|
||||
|
|
|
@ -2158,7 +2158,7 @@ static void unmount_device( struct fd *device_fd )
|
|||
}
|
||||
|
||||
/* default read() routine */
|
||||
obj_handle_t no_fd_read( struct fd *fd, struct async *async, file_pos_t pos )
|
||||
int no_fd_read( struct fd *fd, struct async *async, file_pos_t pos )
|
||||
{
|
||||
set_error( STATUS_OBJECT_TYPE_MISMATCH );
|
||||
return 0;
|
||||
|
@ -2451,7 +2451,7 @@ DECL_HANDLER(read)
|
|||
|
||||
if ((async = create_request_async( current, &req->async )))
|
||||
{
|
||||
reply->wait = fd->fd_ops->read( fd, async, req->pos );
|
||||
reply->wait = async_handoff( async, fd->fd_ops->read( fd, async, req->pos ) );
|
||||
reply->options = fd->options;
|
||||
release_object( async );
|
||||
}
|
||||
|
|
|
@ -52,7 +52,7 @@ struct fd_ops
|
|||
/* get file information */
|
||||
enum server_fd_type (*get_fd_type)(struct fd *fd);
|
||||
/* perform a read on the file */
|
||||
obj_handle_t (*read)(struct fd *, struct async *, file_pos_t );
|
||||
int (*read)(struct fd *, struct async *, file_pos_t );
|
||||
/* perform a write on the file */
|
||||
obj_handle_t (*write)(struct fd *, struct async *, file_pos_t );
|
||||
/* flush the object buffers */
|
||||
|
@ -100,7 +100,7 @@ extern void default_poll_event( struct fd *fd, int event );
|
|||
extern int fd_queue_async( struct fd *fd, struct async *async, int type );
|
||||
extern void fd_async_wake_up( struct fd *fd, int type, unsigned int status );
|
||||
extern void fd_reselect_async( struct fd *fd, struct async_queue *queue );
|
||||
extern obj_handle_t no_fd_read( struct fd *fd, struct async *async, file_pos_t pos );
|
||||
extern int no_fd_read( struct fd *fd, struct async *async, file_pos_t pos );
|
||||
extern obj_handle_t no_fd_write( struct fd *fd, struct async *async, file_pos_t pos );
|
||||
extern obj_handle_t no_fd_flush( struct fd *fd, struct async *async );
|
||||
extern obj_handle_t no_fd_ioctl( struct fd *fd, ioctl_code_t code, struct async *async );
|
||||
|
@ -177,6 +177,7 @@ extern struct async_queue *create_async_queue( struct fd *fd );
|
|||
extern void free_async_queue( struct async_queue *queue );
|
||||
extern struct async *create_async( struct thread *thread, const async_data_t *data, struct iosb *iosb );
|
||||
extern struct async *create_request_async( struct thread *thread, const async_data_t *data );
|
||||
extern obj_handle_t async_handoff( struct async *async, int success );
|
||||
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 );
|
||||
|
|
|
@ -154,7 +154,7 @@ static const struct object_ops named_pipe_ops =
|
|||
|
||||
/* common server and client pipe end functions */
|
||||
static enum server_fd_type pipe_end_get_fd_type( struct fd *fd );
|
||||
static obj_handle_t pipe_end_read( struct fd *fd, struct async *async, file_pos_t pos );
|
||||
static int pipe_end_read( struct fd *fd, struct async *async, file_pos_t pos );
|
||||
static obj_handle_t pipe_end_write( struct fd *fd, struct async *async_data, file_pos_t pos );
|
||||
static void pipe_end_queue_async( struct fd *fd, struct async *async, int type, int count );
|
||||
static void pipe_end_reselect_async( struct fd *fd, struct async_queue *queue );
|
||||
|
@ -810,10 +810,9 @@ static void reselect_write_queue( struct pipe_end *pipe_end )
|
|||
reselect_read_queue( reader );
|
||||
}
|
||||
|
||||
static obj_handle_t pipe_end_read( struct fd *fd, struct async *async, file_pos_t pos )
|
||||
static int pipe_end_read( struct fd *fd, struct async *async, file_pos_t pos )
|
||||
{
|
||||
struct pipe_end *pipe_end = get_fd_user( fd );
|
||||
obj_handle_t handle = 0;
|
||||
|
||||
if (!use_server_io( pipe_end )) return no_fd_read( fd, async, pos );
|
||||
|
||||
|
@ -824,24 +823,11 @@ static obj_handle_t pipe_end_read( struct fd *fd, struct async *async, file_pos_
|
|||
}
|
||||
|
||||
if (!pipe_end->read_q && !(pipe_end->read_q = create_async_queue( fd ))) return 0;
|
||||
if (!(handle = alloc_handle( current->process, async, SYNCHRONIZE, 0 ))) return 0;
|
||||
|
||||
queue_async( pipe_end->read_q, async );
|
||||
reselect_read_queue( pipe_end );
|
||||
set_error( STATUS_PENDING );
|
||||
|
||||
if (!async_is_blocking( async ))
|
||||
{
|
||||
struct iosb *iosb;
|
||||
iosb = async_get_iosb( async );
|
||||
if (iosb->status == STATUS_PENDING)
|
||||
{
|
||||
close_handle( current->process, handle );
|
||||
handle = 0;
|
||||
}
|
||||
release_object( iosb );
|
||||
}
|
||||
return handle;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static obj_handle_t pipe_end_write( struct fd *fd, struct async *async, file_pos_t pos )
|
||||
|
|
Loading…
Reference in a new issue