Commit a9f648ef authored by Sebastian Lackner's avatar Sebastian Lackner Committed by Alexandre Julliard

ntdll: Do not call group cancel callback for finished simple callbacks.

parent be7bcdc0
......@@ -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 );
......
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