Rémi Bernon (@rbernon) commented about dlls/cryptowinrt/tests/crypto.c:
- ok( tmp_handler == NULL, "got handler %p\n", tmp_handler );
- bool_async_handler = default_bool_async_handler;
- bool_async_handler.event = CreateEventW( NULL, FALSE, FALSE, NULL );
- hr = IAsyncOperation_boolean_put_Completed( bool_async, &bool_async_handler.IAsyncOperationCompletedHandler_boolean_iface );
- ok( hr == S_OK, "put_Completed returned %#lx\n", hr );
- ret = WaitForSingleObject( bool_async_handler.event, 5000 );
- ok( !ret, "WaitForSingleObject returned %#lx\n", ret );
- ret = CloseHandle( bool_async_handler.event );
- ok( ret, "CloseHandle failed, error %lu\n", GetLastError() );
- ok( bool_async_handler.invoked, "handler not invoked\n" );
- ok( bool_async_handler.async == bool_async, "got async %p\n", bool_async_handler.async );
- ok( bool_async_handler.status == Completed || broken( bool_async_handler.status == Error ), "got status %u\n", bool_async_handler.status );
- hr = IAsyncOperation_boolean_get_Completed( bool_async, &tmp_handler );
- ok( hr == S_OK, "get_Completed returned %#lx\n", hr );
- ok( tmp_handler == NULL, "got handler %p\n", tmp_handler );
- bool_async_handler = default_bool_async_handler;
Sorry, I missed it but I think this one is also inherently racy, as you can see. The handler being reset to NULL happens asynchronously, some time after the handler has been invoked (after the event is set). You cannot synchronize on this, and so this check will sometimes succeed and sometimes fail depending on whether the main thread resumes from the event wait before or after this happens. You can only remove the test (and you can reduce the wait timeout though it doesn't really matter).