Signed-off-by: Alexey Prokhin alexey@prokhin.ru --- server/completion.c | 25 ++++++++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-)
diff --git a/server/completion.c b/server/completion.c index db04727b93..9e15c1ca07 100644 --- a/server/completion.c +++ b/server/completion.c @@ -48,12 +48,14 @@ struct completion struct object obj; struct list queue; unsigned int depth; + int abandoned; };
static void completion_dump( struct object*, int ); static struct object_type *completion_get_type( struct object *obj ); static int completion_signaled( struct object *obj, struct wait_queue_entry *entry ); static unsigned int completion_map_access( struct object *obj, unsigned int access ); +static int completion_close( struct object *obj, struct process *process, obj_handle_t handle ); static void completion_destroy( struct object * );
static const struct object_ops completion_ops = @@ -75,7 +77,7 @@ static const struct object_ops completion_ops = default_unlink_name, /* unlink_name */ no_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ - no_close_handle, /* close_handle */ + completion_close, /* close_handle */ completion_destroy /* destroy */ };
@@ -88,6 +90,22 @@ struct comp_msg unsigned int status; };
+static int completion_close( struct object *obj, struct process *process, obj_handle_t handle ) +{ + struct completion *completion = (struct completion *) obj; + struct wait_queue_entry *entry; + + LIST_FOR_EACH_ENTRY( entry, &obj->wait_queue, struct wait_queue_entry, entry ) + { + make_wait_abandoned( entry ); + } + + completion->abandoned = 1; + wake_up( &completion->obj, 0 ); + + return 1; +} + static void completion_destroy( struct object *obj) { struct completion *completion = (struct completion *) obj; @@ -118,7 +136,7 @@ static int completion_signaled( struct object *obj, struct wait_queue_entry *ent { struct completion *completion = (struct completion *)obj;
- return !list_empty( &completion->queue ); + return !list_empty( &completion->queue ) || completion->abandoned; }
static unsigned int completion_map_access( struct object *obj, unsigned int access ) @@ -141,6 +159,7 @@ static struct completion *create_completion( struct object *root, const struct u if (get_error() != STATUS_OBJECT_NAME_EXISTS) { list_init( &completion->queue ); + completion->abandoned = 0; completion->depth = 0; } } @@ -224,7 +243,7 @@ DECL_HANDLER(remove_completion)
entry = list_head( &completion->queue ); if (!entry) - set_error( STATUS_PENDING ); + set_error( completion->abandoned ? STATUS_ABANDONED_WAIT_0 : STATUS_PENDING ); else { list_remove( entry );