ntdll: Do not call group cancel callback for finished simple callbacks.
Signed-off-by: Sebastian Lackner <sebastian@fds-team.de> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
be7bcdc0f9
commit
a9f648ef69
|
@ -705,6 +705,14 @@ static void test_tp_work_scheduler(void)
|
|||
pTpReleasePool(pool);
|
||||
}
|
||||
|
||||
static void CALLBACK simple_release_cb(TP_CALLBACK_INSTANCE *instance, void *userdata)
|
||||
{
|
||||
HANDLE *semaphores = userdata;
|
||||
trace("Running simple release callback\n");
|
||||
ReleaseSemaphore(semaphores, 1, NULL);
|
||||
Sleep(200); /* wait until main thread is in TpReleaseCleanupGroupMembers */
|
||||
}
|
||||
|
||||
static void CALLBACK work_release_cb(TP_CALLBACK_INSTANCE *instance, void *userdata, TP_WORK *work)
|
||||
{
|
||||
HANDLE semaphore = userdata;
|
||||
|
@ -1008,6 +1016,18 @@ static void test_tp_group_cancel(void)
|
|||
ok(result == WAIT_OBJECT_0, "WaitForSingleObject returned %u\n", result);
|
||||
pTpReleaseCleanupGroupMembers(group, TRUE, NULL);
|
||||
|
||||
/* terminated simple callbacks should not trigger the group cancel callback */
|
||||
memset(&environment, 0, sizeof(environment));
|
||||
environment.Version = 1;
|
||||
environment.Pool = pool;
|
||||
environment.CleanupGroup = group;
|
||||
environment.CleanupGroupCancelCallback = unexpected_group_cancel_cleanup_cb;
|
||||
status = pTpSimpleTryPost(simple_release_cb, semaphores[1], &environment);
|
||||
ok(!status, "TpSimpleTryPost failed with status %x\n", status);
|
||||
result = WaitForSingleObject(semaphores[1], 1000);
|
||||
ok(result == WAIT_OBJECT_0, "WaitForSingleObject returned %u\n", result);
|
||||
pTpReleaseCleanupGroupMembers(group, TRUE, semaphores);
|
||||
|
||||
/* test cancellation callback for objects with multiple instances */
|
||||
work = NULL;
|
||||
memset(&environment, 0, sizeof(environment));
|
||||
|
|
|
@ -1885,11 +1885,7 @@ static void tp_object_initialize( struct threadpool_object *object, struct threa
|
|||
}
|
||||
|
||||
if (is_simple_callback)
|
||||
{
|
||||
tp_object_prepare_shutdown( object );
|
||||
object->shutdown = TRUE;
|
||||
tp_object_release( object );
|
||||
}
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
|
@ -2185,6 +2181,13 @@ static void CALLBACK threadpool_worker_proc( void *param )
|
|||
RtlEnterCriticalSection( &pool->cs );
|
||||
pool->num_busy_workers--;
|
||||
|
||||
/* Simple callbacks are automatically shutdown after execution. */
|
||||
if (object->type == TP_OBJECT_TYPE_SIMPLE)
|
||||
{
|
||||
tp_object_prepare_shutdown( object );
|
||||
object->shutdown = TRUE;
|
||||
}
|
||||
|
||||
object->num_running_callbacks--;
|
||||
if (!object->num_pending_callbacks && !object->num_running_callbacks)
|
||||
RtlWakeAllConditionVariable( &object->group_finished_event );
|
||||
|
@ -2598,18 +2601,20 @@ VOID WINAPI TpReleaseCleanupGroupMembers( TP_CLEANUP_GROUP *group, BOOL cancel_p
|
|||
{
|
||||
tp_object_wait( object, TRUE );
|
||||
|
||||
/* Execute group cancellation callback if defined, and if this was actually a group cancel. */
|
||||
if ((object->type == TP_OBJECT_TYPE_SIMPLE || !object->shutdown) &&
|
||||
cancel_pending && object->group_cancel_callback)
|
||||
if (!object->shutdown)
|
||||
{
|
||||
TRACE( "executing group cancel callback %p(%p, %p)\n",
|
||||
object->group_cancel_callback, object->userdata, userdata );
|
||||
object->group_cancel_callback( object->userdata, userdata );
|
||||
TRACE( "callback %p returned\n", object->group_cancel_callback );
|
||||
}
|
||||
/* Execute group cancellation callback if defined, and if this was actually a group cancel. */
|
||||
if (cancel_pending && object->group_cancel_callback)
|
||||
{
|
||||
TRACE( "executing group cancel callback %p(%p, %p)\n",
|
||||
object->group_cancel_callback, object->userdata, userdata );
|
||||
object->group_cancel_callback( object->userdata, userdata );
|
||||
TRACE( "callback %p returned\n", object->group_cancel_callback );
|
||||
}
|
||||
|
||||
if (object->type != TP_OBJECT_TYPE_SIMPLE && !object->shutdown)
|
||||
tp_object_release( object );
|
||||
if (object->type != TP_OBJECT_TYPE_SIMPLE)
|
||||
tp_object_release( object );
|
||||
}
|
||||
|
||||
object->shutdown = TRUE;
|
||||
tp_object_release( object );
|
||||
|
|
Loading…
Reference in New Issue