The `gXPCOMThreadsShutDownNotified` assertion exists to discourage
dispatching to a background thread after xpcom-shutdown-threads. This
unfortunately poorly interacts with the nsThreadPool implementation. We
use nsThreadPools all of the way until threads are fully shut down
during ShutdownNonMainThreads, and they dispatch a runnable to a
background thread when starting a new thread.
This patch disables the assertion when NS_DISPATCH_IGNORE_BLOCK_DISPATCH
is specified. This flag already effectively indicates "trust me I am
dispatching to a thread which is in a weird state, this dispatch must
succeed", so seems appropriate to use in this situation, and will avoid
the underlying issue.
The nsThreadPool runnable is already dispatched with this flag set.
Differential Revision: https://phabricator.services.mozilla.com/D190303
This flag is not supported by most event targets and can have unexpected
side effects (namely spinning a nested event loop). All consumers have
been replaced with a new function which is more explicit about this side
effect.
Differential Revision: https://phabricator.services.mozilla.com/D173985
These callers are depending on the existing behaviour which always returns a
thread, and does not respect custom TaskQueues. In the next part, all remaining
callers will be switched to GetCurrentSerialEventTarget.
Differential Revision: https://phabricator.services.mozilla.com/D166606
These callers are depending on the existing behaviour which always returns a
thread, and does not respect custom TaskQueues. In the next part, all remaining
callers will be switched to GetCurrentSerialEventTarget.
Differential Revision: https://phabricator.services.mozilla.com/D166606
`gXPCOMThreadsShutDown` is needed for the assertion in `ThreadEventTarget::Dispatch` but we do not want other shutdown checks to rely on it, as it is too specific for this case. If we ever would really need this checkpoint in time during runtime in release we should consider to make it become a new `ShutdownPhase` in between.
We move the state to `ThreadEventTarget` and have a `DEBUG` only method to prime that assertion over there.
Differential Revision: https://phabricator.services.mozilla.com/D160627
We already have a mechanism for ending threads accepting new messages
when they are shut down, so this only allows tasks started from thread
shutdown tasks during xpcom shutdown to behave consistently.
We already didn't prevent dispatching to the background thread pool at
this time, so it should make little difference there as well, and may
just instead save us from deadlocks where code expects a dispatch to
succeed and it does not during actor shutdown.
This patch both relaxes the check to only be a NS_ASSERTION, and relaxes
it to allow dispatching to the current thread even after
xpcom-shutdown-threads as that thread is definitely still alive.
Differential Revision: https://phabricator.services.mozilla.com/D144592
We already have a mechanism for ending threads accepting new messages
when they are shut down, so this only allows tasks started from thread
shutdown tasks during xpcom shutdown to behave consistently.
We already didn't prevent dispatching to the background thread pool at
this time, so it should make little difference there as well, and may
just instead save us from deadlocks where code expects a dispatch to
succeed and it does not during actor shutdown.
This patch both relaxes the check to only be a NS_ASSERTION, and relaxes
it to allow dispatching to the current thread even after
xpcom-shutdown-threads as that thread is definitely still alive.
Differential Revision: https://phabricator.services.mozilla.com/D144592
DelayedDispatch, in all current implementations, will set up a timer sync and
then Dispatch() a runnable. Since the timer is set up before the Dispatch, there
is a theoretical chance that the timer fires and dispatches a TimerEvent to the
target thread before DelayedDispatch managed to do so. When this happens the
internal DelayedDispatch runnable exits early, i.e., in practice it never runs.
The chance increases dramatically if the Dispatch() to the target in question is
tail dispatched, since the time between DelayedDispatch and the tail could be
non-trivial.
This patch removes the assert that checks that all DelayedRunnables that have
run have also been scheduled, since per the above no such guarantee exists.
Differential Revision: https://phabricator.services.mozilla.com/D112876
DelayedDispatch, in all current implementations, will set up a timer sync and
then Dispatch() a runnable. Since the timer is set up before the Dispatch, there
is a theoretical chance that the timer fires and dispatches a TimerEvent to the
target thread before DelayedDispatch managed to do so. When this happens the
internal DelayedDispatch runnable exits early, i.e., in practice it never runs.
The chance increases dramatically if the Dispatch() to the target in question is
tail dispatched, since the time between DelayedDispatch and the tail could be
non-trivial.
This patch removes the assert that checks that all DelayedRunnables that have
run have also been scheduled, since per the above no such guarantee exists.
Differential Revision: https://phabricator.services.mozilla.com/D112876
Because DelayedRunnables are fire-and-forget, there is no way for a targeted
EventTarget to clean them up on shutdown. Thus if a timer fires after
EventTarget shutdown it will fail to dispatch the timer event, and avoid
releasing the timer callback because it's not on the targeted thread. This
causes a leak as there is a ref-cycle between nsTimerImpl::mCallback and
DelayedRunnable::mTimer.
This patch adds nsIDelayedRunnableObserver for a target to observe which
DelayedRunnables are relying on their timer to run them. This allows the target
to schedule a shutdown task to cancel those timers and release the runnables on
the target thread.
Supported DelayedRunnable targets with this patch are TaskQueues,
eventqueue-based nsThreads and XPCOMThreadWrappers that wrap a supported
nsThread.
An assertion makes sure at runtime that future new uses of DelayedRunnable
target nsIDelayedRunnableObserver-supported event targets.
Differential Revision: https://phabricator.services.mozilla.com/D109781
Because DelayedRunnables are fire-and-forget, there is no way for a targeted
EventTarget to clean them up on shutdown. Thus if a timer fires after
EventTarget shutdown it will fail to dispatch the timer event, and avoid
releasing the timer callback because it's not on the targeted thread. This
causes a leak as there is a ref-cycle between nsTimerImpl::mCallback and
DelayedRunnable::mTimer.
This patch adds nsIDelayedRunnableObserver for a target to observe which
DelayedRunnables are relying on their timer to run them. This allows the target
to schedule a shutdown task to cancel those timers and release the runnables on
the target thread.
Supported DelayedRunnable targets with this patch are TaskQueues,
eventqueue-based nsThreads and XPCOMThreadWrappers that wrap a supported
nsThread.
An assertion makes sure at runtime that future new uses of DelayedRunnable
target nsIDelayedRunnableObserver-supported event targets.
Differential Revision: https://phabricator.services.mozilla.com/D109781
Before P1, GetCurrentThreadSerialEventTarget would have always returned the same data as NS_GetCurrentThread, making the comment incorrect Now it will properly return the running TaskQueue if any.
This change of name more clearly exposes what they are doing, as we aren't always dealing with threads directly; but a nsISerialEventTarget
Differential Revision: https://phabricator.services.mozilla.com/D80354
already_AddRefed destructor assert that it's nullptr.
DelayedDispatch check that the value passed isn't 0 and return an error code, leaving the already_AddRefed untouched.
Differential Revision: https://phabricator.services.mozilla.com/D73821
already_AddRefed destructor assert that it's nullptr.
DelayedDispatch check that the value passed isn't 0 and return an error code, leaving the already_AddRefed untouched.
Differential Revision: https://phabricator.services.mozilla.com/D73821
already_AddRefed destructor assert that it's nullptr.
DelayedDispatch check that the value passed isn't 0 and return an error code, leaving the already_AddRefed untouched.
Differential Revision: https://phabricator.services.mozilla.com/D73821
Virtual thread references are used for IsOnCurrentThread(), which would
spuriously return true when the dangling pointer happened to match that of a
new PRThread.
Differential Revision: https://phabricator.services.mozilla.com/D55765
To remove the blocking inside nsThread::Init, two things needed
to happen:
- Switch the ThreadInitData value passed as the argument for
ThreadFunc to a heap allocation, so that it can outlive the call
to nsThread::Init.
- Initialize mThread and mEventTarget->mThread to the return
value of PR_CreateThread, so that to the callers, checks which
depend on these values being set can continue to function.
Differential Revision: https://phabricator.services.mozilla.com/D41248
GetCurrentPhysicalThread and GetCurrentVirtualThread are, in practice,
identical, as the TLS override that GetCurrentVirtualThread depends on
is never actually set. This simply removes that and renames some things/
deletes some comments.
Differential Revision: https://phabricator.services.mozilla.com/D41247