Bug 1186745 part 5 - Make nsThread::Dispatch() always leak the event if it fails. r=froydnj

--HG--
extra : source : 969aedd9d9b6ee25b679954228f26c043969a29e
This commit is contained in:
Xidorn Quan 2015-10-06 13:00:59 +11:00
Родитель e573430f7d
Коммит c5703449ed
2 изменённых файлов: 17 добавлений и 5 удалений

Просмотреть файл

@ -60,7 +60,10 @@ interface nsIEventTarget : nsISupports
* any thread, and it may be called re-entrantly.
*
* @param event
* The alreadyAddRefed<> event to dispatch
* The alreadyAddRefed<> event to dispatch.
* NOTE that the event will be leaked if it fails to dispatch. Also note
* that if "flags" includes DISPATCH_SYNC, it may return error from Run()
* after a successful dispatch. In that case, the event is not leaked.
* @param flags
* The flags modifying event dispatch. The flags are described in detail
* below.

Просмотреть файл

@ -581,7 +581,9 @@ nsresult
nsThread::DispatchInternal(already_AddRefed<nsIRunnable>&& aEvent, uint32_t aFlags,
nsNestedEventTarget* aTarget)
{
nsCOMPtr<nsIRunnable> event(aEvent);
// We want to leak the reference when we fail to dispatch it, so that
// we won't release the event in a wrong thread.
LeakRefPtr<nsIRunnable> event(Move(aEvent));
if (NS_WARN_IF(!event)) {
return NS_ERROR_INVALID_ARG;
}
@ -592,8 +594,9 @@ nsThread::DispatchInternal(already_AddRefed<nsIRunnable>&& aEvent, uint32_t aFla
}
#ifdef MOZ_TASK_TRACER
nsCOMPtr<nsIRunnable> tracedRunnable = CreateTracedRunnable(event.forget());
nsCOMPtr<nsIRunnable> tracedRunnable = CreateTracedRunnable(event.take());
(static_cast<TracedRunnable*>(tracedRunnable.get()))->DispatchTask();
// XXX tracedRunnable will always leaked when we fail to disptch.
event = tracedRunnable.forget();
#endif
@ -608,10 +611,14 @@ nsThread::DispatchInternal(already_AddRefed<nsIRunnable>&& aEvent, uint32_t aFla
// that to tell us when the event has been processed.
nsRefPtr<nsThreadSyncDispatch> wrapper =
new nsThreadSyncDispatch(thread, event.forget());
new nsThreadSyncDispatch(thread, event.take());
nsresult rv = PutEvent(wrapper, aTarget); // hold a ref
// Don't wait for the event to finish if we didn't dispatch it...
if (NS_FAILED(rv)) {
// PutEvent leaked the wrapper runnable object on failure, so we
// explicitly release this object once for that. Note that this
// object will be released again soon because it exits the scope.
wrapper.get()->Release();
return rv;
}
@ -619,11 +626,13 @@ nsThread::DispatchInternal(already_AddRefed<nsIRunnable>&& aEvent, uint32_t aFla
while (wrapper->IsPending()) {
NS_ProcessNextEvent(thread, true);
}
// NOTE that, unlike the behavior above, the event is not leaked by
// this place, while it is possible that the result is an error.
return wrapper->Result();
}
NS_ASSERTION(aFlags == NS_DISPATCH_NORMAL, "unexpected dispatch flags");
return PutEvent(event.forget(), aTarget);
return PutEvent(event.take(), aTarget);
}
//-----------------------------------------------------------------------------