mstask/tests: Work around race conditions with the task scheduler process.

When a task is created the process scheduler locks and loads it. This
can cause ITaskScheduler_Delete() to fail with a sharing violation if
it is called at the wrong time. Just retry a bit later when that
happens.

This fixes failures mostly in Wine but also in Windows 10 from time
to time in both task and task_scheduler.

Signed-off-by: Francois Gouget <fgouget@icodeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Francois Gouget 2021-05-21 00:13:52 +02:00 committed by Alexandre Julliard
parent cf85253a9c
commit 2e6ae16469
2 changed files with 31 additions and 7 deletions

View File

@ -29,6 +29,9 @@ static ITaskScheduler *scheduler;
static const WCHAR task_name[] = {'T','e','s','t','i','n','g',0}; static const WCHAR task_name[] = {'T','e','s','t','i','n','g',0};
static const WCHAR empty[] = {0}; static const WCHAR empty[] = {0};
extern HRESULT taskscheduler_delete(ITaskScheduler*, const WCHAR*);
static LPCWSTR path_resolve_name(LPCWSTR base_name) static LPCWSTR path_resolve_name(LPCWSTR base_name)
{ {
static WCHAR buffer[MAX_PATH]; static WCHAR buffer[MAX_PATH];
@ -552,7 +555,7 @@ static void test_Run(void)
HRESULT hr, status; HRESULT hr, status;
/* cleanup after previous runs */ /* cleanup after previous runs */
ITaskScheduler_Delete(scheduler, wine_test_runW); taskscheduler_delete(scheduler, wine_test_runW);
hr = ITaskScheduler_NewWorkItem(scheduler, wine_test_runW, &CLSID_CTask, hr = ITaskScheduler_NewWorkItem(scheduler, wine_test_runW, &CLSID_CTask,
&IID_ITask, (IUnknown **)&task); &IID_ITask, (IUnknown **)&task);
@ -679,7 +682,7 @@ static void test_Run(void)
else else
ITask_Release(task); ITask_Release(task);
hr = ITaskScheduler_Delete(scheduler, wine_test_runW); hr = taskscheduler_delete(scheduler, wine_test_runW);
ok(hr == S_OK, "got %#x\n", hr); ok(hr == S_OK, "got %#x\n", hr);
} }

View File

@ -31,6 +31,27 @@ static ITaskScheduler *test_task_scheduler;
static const WCHAR does_not_existW[] = {'\\','\\','d','o','e','s','_','n','o','t','_','e','x','i','s','t',0}; static const WCHAR does_not_existW[] = {'\\','\\','d','o','e','s','_','n','o','t','_','e','x','i','s','t',0};
HRESULT taskscheduler_delete(ITaskScheduler *scheduler, const WCHAR *name)
{
HRESULT hr;
int i = 0;
while (1)
{
hr = ITaskScheduler_Delete(scheduler, name);
if (hr != HRESULT_FROM_WIN32(ERROR_SHARING_VIOLATION)) break;
if (++i == 5) break;
/* The task scheduler locked the file to load the task (see
* ITaskScheduler_Activate()). It should be done soon.
*/
trace("Got a sharing violation deleting %s, retrying...\n", wine_dbgstr_w(name));
Sleep(100);
}
return hr;
}
static void test_NewWorkItem(void) static void test_NewWorkItem(void)
{ {
HRESULT hres; HRESULT hres;
@ -225,7 +246,7 @@ static void test_Enum(void)
ok(hr == S_OK, "got %#x\n", hr); ok(hr == S_OK, "got %#x\n", hr);
/* cleanup after previous runs */ /* cleanup after previous runs */
ITaskScheduler_Delete(scheduler, Task1); taskscheduler_delete(scheduler, Task1);
hr = ITaskScheduler_NewWorkItem(scheduler, Task1, &CLSID_CTask, &IID_ITask, (IUnknown **)&task); hr = ITaskScheduler_NewWorkItem(scheduler, Task1, &CLSID_CTask, &IID_ITask, (IUnknown **)&task);
ok(hr == S_OK, "got %#x\n", hr); ok(hr == S_OK, "got %#x\n", hr);
@ -291,7 +312,7 @@ static void test_Enum(void)
IEnumWorkItems_Release(tasks); IEnumWorkItems_Release(tasks);
hr = ITaskScheduler_Delete(scheduler, Task1); hr = taskscheduler_delete(scheduler, Task1);
ok(hr == S_OK, "got %#x\n", hr); ok(hr == S_OK, "got %#x\n", hr);
ITaskScheduler_Release(scheduler); ITaskScheduler_Release(scheduler);
@ -494,11 +515,11 @@ static void test_task_storage(void)
test_save_task_curfile(task); test_save_task_curfile(task);
hr = ITaskScheduler_Delete(scheduler, Task1); hr = taskscheduler_delete(scheduler, Task1);
ok(hr == S_OK, "got %#x\n", hr); ok(hr == S_OK, "got %#x\n", hr);
hr = ITaskScheduler_Delete(scheduler, Task2); hr = taskscheduler_delete(scheduler, Task2);
ok(hr == S_OK, "got %#x\n", hr); ok(hr == S_OK, "got %#x\n", hr);
hr = ITaskScheduler_Delete(scheduler, Task3); hr = taskscheduler_delete(scheduler, Task3);
ok(hr == S_OK, "got %#x\n", hr); ok(hr == S_OK, "got %#x\n", hr);
ITask_Release(task); ITask_Release(task);