Commit 57095a91 authored by Paul Gofman's avatar Paul Gofman Committed by Alexandre Julliard

server: Cancel socket asyncs when the last handle in process is closed.

parent 6360f569
......@@ -2858,17 +2858,20 @@ static void test_async_cancel_on_handle_close(void)
closesocket(listener);
/* Canceled asyncs with completion port and no event do not update IOSB before removing completion. */
todo_wine_if(other_process && tests[i].apc_context && !tests[i].event)
ok(io.Status == 0xcccccccc, "got %#lx\n", io.Status);
memset(&io, 0xcc, sizeof(io));
key = 0xcc;
value = 0;
ret = NtRemoveIoCompletion(port, &key, &value, &io, &zero);
if (other_process && tests[i].apc_context && !tests[i].event)
{
todo_wine ok(!ret, "got %#lx\n", ret);
todo_wine ok(!key, "got key %#Ix\n", key);
todo_wine ok(value == 0xdeadbeef, "got value %#Ix\n", value);
todo_wine ok(io.Status == STATUS_CANCELLED, "got %#lx\n", io.Status);
ok(!ret, "got %#lx\n", ret);
ok(!key, "got key %#Ix\n", key);
ok(value == 0xdeadbeef, "got value %#Ix\n", value);
ok(io.Status == STATUS_CANCELLED, "got %#lx\n", io.Status);
}
else
{
......
......@@ -614,6 +614,28 @@ void cancel_process_asyncs( struct process *process )
cancel_async( process, NULL, NULL, 0 );
}
int async_close_obj_handle( struct object *obj, struct process *process, obj_handle_t handle )
{
/* Handle a special case when the last object handle in the given process is closed.
* If this is the last object handle overall that is handled in object's close_handle and
* destruction. */
struct async *async;
if (obj->handle_count == 1 || get_obj_handle_count( process, obj ) != 1) return 1;
restart:
LIST_FOR_EACH_ENTRY( async, &process->asyncs, struct async, process_entry )
{
if (async->terminated || async->canceled || get_fd_user( async->fd ) != obj) continue;
if (!async->completion || !async->data.apc_context || async->event) continue;
async->canceled = 1;
fd_cancel_async( async->fd, async );
goto restart;
}
return 1;
}
void cancel_terminating_thread_asyncs( struct thread *thread )
{
struct async *async;
......
......@@ -246,6 +246,7 @@ extern struct thread *async_get_thread( struct async *async );
extern struct async *find_pending_async( struct async_queue *queue );
extern void cancel_process_asyncs( struct process *process );
extern void cancel_terminating_thread_asyncs( struct thread *thread );
extern int async_close_obj_handle( struct object *obj, struct process *process, obj_handle_t handle );
static inline void init_async_queue( struct async_queue *queue )
{
......
......@@ -520,6 +520,21 @@ obj_handle_t find_inherited_handle( struct process *process, const struct object
return 0;
}
/* return number of open handles to the object in the process */
unsigned int get_obj_handle_count( struct process *process, const struct object *obj )
{
struct handle_table *table = process->handles;
struct handle_entry *ptr;
unsigned int count = 0;
int i;
if (!table) return 0;
for (i = 0, ptr = table->entries; i <= table->last; i++, ptr++)
if (ptr->ptr == obj) ++count;
return count;
}
/* get/set the handle reserved flags */
/* return the old flags (or -1 on error) */
static int set_handle_flags( struct process *process, obj_handle_t handle, int mask, int flags )
......
......@@ -48,6 +48,7 @@ extern obj_handle_t open_object( struct process *process, obj_handle_t parent, u
const struct object_ops *ops, const struct unicode_str *name,
unsigned int attr );
extern obj_handle_t find_inherited_handle( struct process *process, const struct object_ops *ops );
extern unsigned int get_obj_handle_count( struct process *process, const struct object *obj );
extern void close_process_handles( struct process *process );
extern struct handle_table *alloc_handle_table( struct process *process, int count );
extern struct handle_table *copy_handle_table( struct process *process, struct process *parent,
......
......@@ -1655,8 +1655,7 @@ static int sock_close_handle( struct object *obj, struct process *process, obj_h
if (signaled) complete_async_poll( poll_req, STATUS_SUCCESS );
}
}
return 1;
return async_close_obj_handle( obj, process, handle );
}
static void sock_destroy( struct object *obj )
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment