server: Cancel socket asyncs when the last handle in process is closed.
This commit is contained in:
parent
6360f56931
commit
57095a91b0
6 changed files with 47 additions and 6 deletions
|
@ -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 )
|
||||
|
|
Loading…
Add table
Reference in a new issue