Commit f3bab6c5 authored by Zhiyi Zhang's avatar Zhiyi Zhang Committed by Alexandre Julliard

rtworkq: Avoid closing a thread pool object while its callbacks are running.

Consider a thread A running scheduled_item_cancelable_callback() and a thread B running queue_cancel_item(), which is the scenario from canceling a work item right after it gets submitted by RtwqScheduleWorkItem(). When the CloseThreadpoolTimer() call in queue_cancel_item() in thread B runs before the queue_release_pending_item() in scheduled_item_cancelable_callback() in thread A, scheduled_item_cancelable_callback() ends up calling work_item_Release() and CloseThreadpoolTimer() is called again for the same timer object. So the thread pool timer object end up getting released while the scheduled_item_cancelable_callback() is running, triggering the '!object->num_running_callbacks' assertion in tp_object_release(). This is actually a double free but the assertion happens before the second free could happen. The same thing could happen for thread pool wait objects as well. Fix mf and mfmediaengine tests sometimes trigger the '!object->num_running_callbacks' assertion. Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=55724
parent c5f9d918
...@@ -892,9 +892,13 @@ static HRESULT queue_cancel_item(struct queue *queue, RTWQWORKITEM_KEY key) ...@@ -892,9 +892,13 @@ static HRESULT queue_cancel_item(struct queue *queue, RTWQWORKITEM_KEY key)
IRtwqAsyncResult_SetStatus(item->result, RTWQ_E_OPERATION_CANCELLED); IRtwqAsyncResult_SetStatus(item->result, RTWQ_E_OPERATION_CANCELLED);
invoke_async_callback(item->result); invoke_async_callback(item->result);
CloseThreadpoolWait(item->u.wait_object); CloseThreadpoolWait(item->u.wait_object);
item->u.wait_object = NULL;
} }
else if ((key & SCHEDULED_ITEM_KEY_MASK) == SCHEDULED_ITEM_KEY_MASK) else if ((key & SCHEDULED_ITEM_KEY_MASK) == SCHEDULED_ITEM_KEY_MASK)
{
CloseThreadpoolTimer(item->u.timer_object); CloseThreadpoolTimer(item->u.timer_object);
item->u.timer_object = NULL;
}
else else
WARN("Unknown item key mask %#I64x.\n", key); WARN("Unknown item key mask %#I64x.\n", key);
queue_release_pending_item(item); queue_release_pending_item(item);
......
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