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:
Jacek Caban 2017-06-26 12:17:36 +02:00 committed by Alexandre Julliard
parent e0760ce933
commit 0fb6099b01
5 changed files with 52 additions and 31 deletions

View file

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

View file

@ -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, &params, 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, &params, 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, &params, 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, &params, async );
if (!irp) return 0;
handle = queue_irp( file, irp, async );
handle = queue_irp( file, irp, async, 1 );
release_object( irp );
return handle;
}

View file

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

View file

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

View file

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