Bug 1825360 - Remove the NS_DISPATCH_SYNC flag, r=necko-reviewers,geckoview-reviewers,media-playback-reviewers,karlt,jesup,m_kato,emilio

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
This commit is contained in:
Nika Layzell 2023-03-30 16:53:51 +00:00
parent 1118f48cad
commit d57c9498f6
50 changed files with 574 additions and 649 deletions

View file

@ -9,6 +9,7 @@
#include "mozilla/ipc/BackgroundUtils.h"
#include "mozilla/ipc/PBackgroundSharedTypes.h"
#include "nsIEventTarget.h"
#include "nsISerialEventTarget.h"
#include "nsIURIMutator.h"
#include "nsNetUtil.h"
#include "nsPrintfCString.h"
@ -18,10 +19,13 @@ namespace mozilla {
template <typename F>
void RunOnBackgroundThread(F&& aFunction) {
ASSERT_NS_SUCCEEDED(NS_DispatchBackgroundTask(
nsCOMPtr<nsISerialEventTarget> backgroundQueue;
ASSERT_NS_SUCCEEDED(NS_CreateBackgroundTaskQueue(
"RunOnBackgroundThread", getter_AddRefs(backgroundQueue)));
ASSERT_NS_SUCCEEDED(NS_DispatchAndSpinEventLoopUntilComplete(
"RunOnBackgroundThread"_ns, backgroundQueue,
NS_NewRunnableFunction("RunOnBackgroundThread",
std::forward<F>(aFunction)),
NS_DISPATCH_SYNC));
std::forward<F>(aFunction))));
}
TEST(BackgroundThreadPrincipal, CreateContent)

View file

@ -60,29 +60,27 @@ class TestFileSystemQuotaClient
quota::QuotaManager* quotaManager = quota::QuotaManager::Get();
ASSERT_TRUE(quotaManager);
quotaManager->IOThread()->Dispatch(
NS_NewRunnableFunction(
"TestFileSystemQuotaClient",
[]() {
quota::QuotaManager* qm = quota::QuotaManager::Get();
ASSERT_TRUE(qm);
NS_DispatchAndSpinEventLoopUntilComplete(
"TestFileSystemQuotaClient"_ns, quotaManager->IOThread(),
NS_NewRunnableFunction("TestFileSystemQuotaClient", []() {
quota::QuotaManager* qm = quota::QuotaManager::Get();
ASSERT_TRUE(qm);
ASSERT_NSEQ(NS_OK, qm->EnsureStorageIsInitialized());
ASSERT_NSEQ(NS_OK, qm->EnsureStorageIsInitialized());
ASSERT_NSEQ(NS_OK, qm->EnsureTemporaryStorageIsInitialized());
ASSERT_NSEQ(NS_OK, qm->EnsureTemporaryStorageIsInitialized());
const quota::OriginMetadata& testOriginMeta =
GetTestQuotaOriginMetadata();
const quota::OriginMetadata& testOriginMeta =
GetTestQuotaOriginMetadata();
auto dirInfoRes = qm->EnsureTemporaryOriginIsInitialized(
quota::PERSISTENCE_TYPE_DEFAULT, testOriginMeta);
if (dirInfoRes.isErr()) {
ASSERT_NSEQ(NS_OK, dirInfoRes.unwrapErr());
}
auto dirInfoRes = qm->EnsureTemporaryOriginIsInitialized(
quota::PERSISTENCE_TYPE_DEFAULT, testOriginMeta);
if (dirInfoRes.isErr()) {
ASSERT_NSEQ(NS_OK, dirInfoRes.unwrapErr());
}
qm->EnsureQuotaForOrigin(testOriginMeta);
}),
NS_DISPATCH_SYNC);
qm->EnsureQuotaForOrigin(testOriginMeta);
}));
};
PerformOnBackgroundThread(std::move(backgroundTask));

View file

@ -6377,7 +6377,8 @@ nsresult DispatchAndReturnFileReferences(
QuotaManager* const quotaManager = QuotaManager::Get();
MOZ_ASSERT(quotaManager);
// XXX can't we simply use NS_DISPATCH_SYNC instead of using a monitor?
// XXX can't we simply use NS_DispatchAndSpinEventLoopUntilComplete instead of
// using a monitor?
QM_TRY(MOZ_TO_RESULT(quotaManager->IOThread()->Dispatch(
NS_NewRunnableFunction("GetFileReferences", std::move(lambda)),
NS_DISPATCH_NORMAL)));

View file

@ -799,7 +799,8 @@ void AudioCallbackDriver::Shutdown() {
RefPtr<AsyncCubebTask> releaseEvent =
new AsyncCubebTask(this, AsyncCubebOperation::SHUTDOWN);
releaseEvent->Dispatch(NS_DISPATCH_SYNC);
releaseEvent->DispatchAndSpinEventLoopUntilComplete(
"AudioCallbackDriver::Shutdown"_ns);
}
/* static */

View file

@ -808,6 +808,12 @@ class AsyncCubebTask : public Runnable {
return mDriver->mInitShutdownThread->Dispatch(this, aFlags);
}
nsresult DispatchAndSpinEventLoopUntilComplete(
const nsACString& aVeryGoodReasonToDoThis) {
return NS_DispatchAndSpinEventLoopUntilComplete(
aVeryGoodReasonToDoThis, mDriver->mInitShutdownThread, do_AddRef(this));
}
protected:
virtual ~AsyncCubebTask();

View file

@ -41,11 +41,12 @@ static already_AddRefed<SourceSurface> GetSourceSurface(Image* aImage) {
// GLImage::GetAsSourceSurface() only supports main thread
RefPtr<SourceSurface> surf;
NS_DispatchToMainThread(
NS_DispatchAndSpinEventLoopUntilComplete(
"ImageToI420::GLImage::GetSourceSurface"_ns,
mozilla::GetMainThreadSerialEventTarget(),
NS_NewRunnableFunction(
"ImageToI420::GLImage::GetSourceSurface",
[&aImage, &surf]() { surf = aImage->GetAsSourceSurface(); }),
NS_DISPATCH_SYNC);
[&aImage, &surf]() { surf = aImage->GetAsSourceSurface(); }));
return surf.forget();
}

View file

@ -2070,9 +2070,9 @@ static void ForeachObservedPref(const Function& aFunction) {
#endif
}
// NOTE: never Dispatch(....,NS_DISPATCH_SYNC) to the MediaManager
// thread from the MainThread, as we NS_DISPATCH_SYNC to MainThread
// from MediaManager thread.
// NOTE: never NS_DispatchAndSpinEventLoopUntilComplete to the MediaManager
// thread from the MainThread, as we NS_DispatchAndSpinEventLoopUntilComplete to
// MainThread from MediaManager thread.
// Guaranteed never to return nullptr.
/* static */

View file

@ -194,9 +194,9 @@ class MediaManager final : public nsIMediaManagerService,
public:
static already_AddRefed<MediaManager> GetInstance();
// NOTE: never Dispatch(....,NS_DISPATCH_SYNC) to the MediaManager
// thread from the MainThread, as we NS_DISPATCH_SYNC to MainThread
// from MediaManager thread.
// NOTE: never NS_DispatchAndSpinEventLoopUntilComplete to the MediaManager
// thread from the MainThread, as we NS_DispatchAndSpinEventLoopUntilComplete
// to MainThread from MediaManager thread.
static MediaManager* Get();
static MediaManager* GetIfExists();
static void StartupInit();

View file

@ -17,6 +17,7 @@
#include "mozilla/EventDispatcher.h"
#include "mozilla/dom/Document.h"
#include "mozilla/dom/PluginCrashedEvent.h"
#include "nsThreadUtils.h"
#if defined(XP_LINUX) && defined(MOZ_SANDBOX)
# include "mozilla/SandboxInfo.h"
#endif
@ -354,7 +355,7 @@ nsCOMPtr<nsIAsyncShutdownClient> GeckoMediaPluginService::GetShutdownBarrier() {
nsresult GeckoMediaPluginService::GMPDispatch(nsIRunnable* event,
uint32_t flags) {
nsCOMPtr<nsIRunnable> r(event);
return GMPDispatch(r.forget());
return GMPDispatch(r.forget(), flags);
}
nsresult GeckoMediaPluginService::GMPDispatch(

View file

@ -19,6 +19,7 @@
#include "mozilla/SchedulerGroup.h"
#include "mozilla/dom/ContentParent.h"
#include "mozilla/ipc/Endpoint.h"
#include "nsThreadUtils.h"
#if defined(XP_LINUX) && defined(MOZ_SANDBOX)
# include "mozilla/SandboxInfo.h"
#endif
@ -813,8 +814,12 @@ nsresult GeckoMediaPluginServiceParent::EnsurePluginsOnDiskScanned() {
// cause an event to be dispatched to which scans for plugins. We
// dispatch a sync event to the GMP thread here in order to wait until
// after the GMP thread has scanned any paths in MOZ_GMP_PATH.
nsresult rv = GMPDispatch(new mozilla::Runnable("GMPDummyRunnable"),
NS_DISPATCH_SYNC);
nsCOMPtr<nsIThread> thread;
nsresult rv = GetThread(getter_AddRefs(thread));
NS_ENSURE_SUCCESS(rv, rv);
rv = NS_DispatchAndSpinEventLoopUntilComplete(
"GeckoMediaPluginServiceParent::EnsurePluginsOnDiskScanned"_ns, thread,
MakeAndAddRef<mozilla::Runnable>("GMPDummyRunnable"));
NS_ENSURE_SUCCESS(rv, rv);
MOZ_ASSERT(mScannedPluginOnDisk, "Should have scanned MOZ_GMP_PATH by now");
}
@ -1906,10 +1911,10 @@ bool GMPServiceParent::Create(Endpoint<PGMPServiceParent>&& aGMPService) {
serviceParent = new GMPServiceParent(gmp);
}
bool ok;
nsresult rv = gmpThread->Dispatch(
new OpenPGMPServiceParent(std::move(serviceParent),
std::move(aGMPService), &ok),
NS_DISPATCH_SYNC);
nsresult rv = NS_DispatchAndSpinEventLoopUntilComplete(
"GMPServiceParent::Create"_ns, gmpThread,
do_AddRef(new OpenPGMPServiceParent(std::move(serviceParent),
std::move(aGMPService), &ok)));
if (NS_WARN_IF(NS_FAILED(rv) || !ok)) {
return false;

View file

@ -198,8 +198,9 @@ static void ClearCDMStorage(already_AddRefed<nsIRunnable> aContinuation,
}
static void SimulatePBModeExit() {
NS_DispatchToMainThread(new NotifyObserversTask("last-pb-context-exited"),
NS_DISPATCH_SYNC);
NS_DispatchAndSpinEventLoopUntilComplete(
"SimulatePBModeExit"_ns, GetMainThreadSerialEventTarget(),
MakeAndAddRef<NotifyObserversTask>("last-pb-context-exited"));
}
class TestGetNodeIdCallback : public GetNodeIdCallback {

View file

@ -264,13 +264,13 @@ bool GMPRemoveTest::CreateVideoDecoder(nsCString aNodeId) {
codec.mGMPApiVersion = 33;
nsTArray<uint8_t> empty;
mGMPThread->Dispatch(
NS_DispatchAndSpinEventLoopUntilComplete(
"GMPVideoDecoderProxy::InitDecode"_ns, mGMPThread,
NewNonOwningRunnableMethod<const GMPVideoCodec&, const nsTArray<uint8_t>&,
GMPVideoDecoderCallbackProxy*, int32_t>(
"GMPVideoDecoderProxy::InitDecode", decoder,
&GMPVideoDecoderProxy::InitDecode, codec, empty, this,
1 /* core count */),
NS_DISPATCH_SYNC);
1 /* core count */));
if (mDecoder) {
CloseVideoDecoder();
@ -317,10 +317,10 @@ void GMPRemoveTest::gmp_GetVideoDecoder(nsCString aNodeId,
}
void GMPRemoveTest::CloseVideoDecoder() {
mGMPThread->Dispatch(
NS_DispatchAndSpinEventLoopUntilComplete(
"GMPVideoDecoderProxy::Close"_ns, mGMPThread,
NewNonOwningRunnableMethod("GMPVideoDecoderProxy::Close", mDecoder,
&GMPVideoDecoderProxy::Close),
NS_DISPATCH_SYNC);
&GMPVideoDecoderProxy::Close));
mDecoder = nullptr;
mHost = nullptr;

View file

@ -809,9 +809,9 @@ void DeleteSurfaceDescriptorUserData(void* aClosure) {
already_AddRefed<SourceSurface> RemoteDecoderManagerChild::Readback(
const SurfaceDescriptorGPUVideo& aSD) {
// We can't use NS_DISPATCH_SYNC here since that can spin the event
// loop while it waits. This function can be called from JS and we
// don't want that to happen.
// We can't use NS_DispatchAndSpinEventLoopUntilComplete here since that will
// spin the event loop while it waits. This function can be called from JS and
// we don't want that to happen.
nsCOMPtr<nsISerialEventTarget> managerThread = GetManagerThread();
if (!managerThread) {
return nullptr;

View file

@ -180,8 +180,9 @@ static inline nsresult RUN_ON_THREAD(
static inline nsresult RUN_ON_THREAD(
nsIEventTarget* thread,
detail::runnable_args_base<detail::ReturnsResult>* runnable) {
return detail::RunOnThreadInternal(
thread, static_cast<nsIRunnable*>(runnable), NS_DISPATCH_SYNC);
return NS_DispatchAndSpinEventLoopUntilComplete(
"webrtc RUN_ON_THREAD"_ns, thread,
do_AddRef(static_cast<nsIRunnable*>(runnable)));
}
#ifdef DEBUG

View file

@ -129,39 +129,33 @@ class StunTest : public MtransportTest {
}
// Make sure NrIceCtx is in a testable state.
test_utils_->sts_target()->Dispatch(
WrapRunnableNM(&NrIceCtx::internal_DeinitializeGlobal),
NS_DISPATCH_SYNC);
test_utils_->SyncDispatchToSTS(
WrapRunnableNM(&NrIceCtx::internal_DeinitializeGlobal));
// NB: NrIceCtx::internal_DeinitializeGlobal destroys the RLogConnector
// singleton.
RLogConnector::CreateInstance();
test_utils_->sts_target()->Dispatch(
WrapRunnableNM(&TestStunServer::GetInstance, AF_INET),
NS_DISPATCH_SYNC);
test_utils_->sts_target()->Dispatch(
WrapRunnableNM(&TestStunServer::GetInstance, AF_INET6),
NS_DISPATCH_SYNC);
test_utils_->SyncDispatchToSTS(
WrapRunnableNM(&TestStunServer::GetInstance, AF_INET));
test_utils_->SyncDispatchToSTS(
WrapRunnableNM(&TestStunServer::GetInstance, AF_INET6));
test_utils_->sts_target()->Dispatch(
WrapRunnableNM(&TestStunTcpServer::GetInstance, AF_INET),
NS_DISPATCH_SYNC);
test_utils_->sts_target()->Dispatch(
WrapRunnableNM(&TestStunTcpServer::GetInstance, AF_INET6),
NS_DISPATCH_SYNC);
test_utils_->SyncDispatchToSTS(
WrapRunnableNM(&TestStunTcpServer::GetInstance, AF_INET));
test_utils_->SyncDispatchToSTS(
WrapRunnableNM(&TestStunTcpServer::GetInstance, AF_INET6));
}
void TearDown() override {
test_utils_->sts_target()->Dispatch(
WrapRunnableNM(&NrIceCtx::internal_DeinitializeGlobal),
NS_DISPATCH_SYNC);
test_utils_->SyncDispatchToSTS(
WrapRunnableNM(&NrIceCtx::internal_DeinitializeGlobal));
test_utils_->sts_target()->Dispatch(
WrapRunnableNM(&TestStunServer::ShutdownInstance), NS_DISPATCH_SYNC);
test_utils_->SyncDispatchToSTS(
WrapRunnableNM(&TestStunServer::ShutdownInstance));
test_utils_->sts_target()->Dispatch(
WrapRunnableNM(&TestStunTcpServer::ShutdownInstance), NS_DISPATCH_SYNC);
test_utils_->SyncDispatchToSTS(
WrapRunnableNM(&TestStunTcpServer::ShutdownInstance));
RLogConnector::DestroyInstance();
@ -310,9 +304,8 @@ class SchedulableTrickleCandidate {
}
void Schedule(unsigned int ms) {
test_utils_->sts_target()->Dispatch(
WrapRunnable(this, &SchedulableTrickleCandidate::Schedule_s, ms),
NS_DISPATCH_SYNC);
test_utils_->SyncDispatchToSTS(
WrapRunnable(this, &SchedulableTrickleCandidate::Schedule_s, ms));
}
void Schedule_s(unsigned int ms) {
@ -396,8 +389,7 @@ class IceTestPeer : public sigslot::has_slots<> {
}
~IceTestPeer() {
test_utils_->sts_target()->Dispatch(
WrapRunnable(this, &IceTestPeer::Shutdown), NS_DISPATCH_SYNC);
test_utils_->SyncDispatchToSTS(WrapRunnable(this, &IceTestPeer::Shutdown));
// Give the ICE destruction callback time to fire before
// we destroy the resolver.
@ -439,9 +431,8 @@ class IceTestPeer : public sigslot::has_slots<> {
}
void AddStream(int components) {
test_utils_->sts_target()->Dispatch(
WrapRunnable(this, &IceTestPeer::AddStream_s, components),
NS_DISPATCH_SYNC);
test_utils_->SyncDispatchToSTS(
WrapRunnable(this, &IceTestPeer::AddStream_s, components));
}
void RemoveStream_s(size_t index) {
@ -449,9 +440,8 @@ class IceTestPeer : public sigslot::has_slots<> {
}
void RemoveStream(size_t index) {
test_utils_->sts_target()->Dispatch(
WrapRunnable(this, &IceTestPeer::RemoveStream_s, index),
NS_DISPATCH_SYNC);
test_utils_->SyncDispatchToSTS(
WrapRunnable(this, &IceTestPeer::RemoveStream_s, index));
}
RefPtr<NrIceMediaStream> GetStream_s(size_t index) {
@ -527,18 +517,16 @@ class IceTestPeer : public sigslot::has_slots<> {
bool obfuscate_host_addresses = false) {
nsresult res;
test_utils_->sts_target()->Dispatch(
test_utils_->SyncDispatchToSTS(
WrapRunnableRet(&res, ice_ctx_, &NrIceCtx::StartGathering,
default_route_only, obfuscate_host_addresses),
NS_DISPATCH_SYNC);
default_route_only, obfuscate_host_addresses));
ASSERT_TRUE(NS_SUCCEEDED(res));
}
void SetCtxFlags(bool default_route_only) {
test_utils_->sts_target()->Dispatch(
WrapRunnable(ice_ctx_, &NrIceCtx::SetCtxFlags, default_route_only),
NS_DISPATCH_SYNC);
test_utils_->SyncDispatchToSTS(
WrapRunnable(ice_ctx_, &NrIceCtx::SetCtxFlags, default_route_only));
}
nsTArray<NrIceStunAddr> GetStunAddrs() { return ice_ctx_->GetStunAddrs(); }
@ -676,9 +664,8 @@ class IceTestPeer : public sigslot::has_slots<> {
}
bool is_ready(size_t stream) {
bool result;
test_utils_->sts_target()->Dispatch(
WrapRunnableRet(&result, this, &IceTestPeer::is_ready_s, stream),
NS_DISPATCH_SYNC);
test_utils_->SyncDispatchToSTS(
WrapRunnableRet(&result, this, &IceTestPeer::is_ready_s, stream));
return result;
}
bool ice_connected() { return ice_connected_; }
@ -688,8 +675,8 @@ class IceTestPeer : public sigslot::has_slots<> {
size_t sent() { return sent_; }
void RestartIce() {
test_utils_->sts_target()->Dispatch(
WrapRunnable(this, &IceTestPeer::RestartIce_s), NS_DISPATCH_SYNC);
test_utils_->SyncDispatchToSTS(
WrapRunnable(this, &IceTestPeer::RestartIce_s));
}
void RestartIce_s() {
@ -706,9 +693,8 @@ class IceTestPeer : public sigslot::has_slots<> {
}
void RollbackIceRestart() {
test_utils_->sts_target()->Dispatch(
WrapRunnable(this, &IceTestPeer::RollbackIceRestart_s),
NS_DISPATCH_SYNC);
test_utils_->SyncDispatchToSTS(
WrapRunnable(this, &IceTestPeer::RollbackIceRestart_s));
}
void RollbackIceRestart_s() {
@ -768,10 +754,8 @@ class IceTestPeer : public sigslot::has_slots<> {
void Connect(IceTestPeer* remote, TrickleMode trickle_mode,
bool start = true) {
test_utils_->sts_target()->Dispatch(
WrapRunnable(this, &IceTestPeer::Connect_s, remote, trickle_mode,
start),
NS_DISPATCH_SYNC);
test_utils_->SyncDispatchToSTS(WrapRunnable(this, &IceTestPeer::Connect_s,
remote, trickle_mode, start));
}
void SimulateTrickle(size_t stream) {
@ -916,14 +900,13 @@ class IceTestPeer : public sigslot::has_slots<> {
}
void DumpAndCheckActiveCandidates() {
test_utils_->sts_target()->Dispatch(
WrapRunnable(this, &IceTestPeer::DumpAndCheckActiveCandidates_s),
NS_DISPATCH_SYNC);
test_utils_->SyncDispatchToSTS(
WrapRunnable(this, &IceTestPeer::DumpAndCheckActiveCandidates_s));
}
void Close() {
test_utils_->sts_target()->Dispatch(
WrapRunnable(ice_ctx_, &NrIceCtx::destroy_peer_ctx), NS_DISPATCH_SYNC);
test_utils_->SyncDispatchToSTS(
WrapRunnable(ice_ctx_, &NrIceCtx::destroy_peer_ctx));
}
void Shutdown() {
@ -949,15 +932,12 @@ class IceTestPeer : public sigslot::has_slots<> {
void StartChecks() {
nsresult res;
test_utils_->sts_target()->Dispatch(
WrapRunnableRet(
&res, ice_ctx_, &NrIceCtx::SetControlling,
offerer_ ? NrIceCtx::ICE_CONTROLLING : NrIceCtx::ICE_CONTROLLED),
NS_DISPATCH_SYNC);
test_utils_->SyncDispatchToSTS(WrapRunnableRet(
&res, ice_ctx_, &NrIceCtx::SetControlling,
offerer_ ? NrIceCtx::ICE_CONTROLLING : NrIceCtx::ICE_CONTROLLED));
// Now start checks
test_utils_->sts_target()->Dispatch(
WrapRunnableRet(&res, ice_ctx_, &NrIceCtx::StartChecks),
NS_DISPATCH_SYNC);
test_utils_->SyncDispatchToSTS(
WrapRunnableRet(&res, ice_ctx_, &NrIceCtx::StartChecks));
ASSERT_TRUE(NS_SUCCEEDED(res));
}
@ -1032,10 +1012,8 @@ class IceTestPeer : public sigslot::has_slots<> {
nsresult GetCandidatePairs(size_t stream_index,
std::vector<NrIceCandidatePair>* pairs) {
nsresult v;
test_utils_->sts_target()->Dispatch(
WrapRunnableRet(&v, this, &IceTestPeer::GetCandidatePairs_s,
stream_index, pairs),
NS_DISPATCH_SYNC);
test_utils_->SyncDispatchToSTS(WrapRunnableRet(
&v, this, &IceTestPeer::GetCandidatePairs_s, stream_index, pairs));
return v;
}
@ -1235,10 +1213,8 @@ class IceTestPeer : public sigslot::has_slots<> {
void ParseCandidate(size_t i, const std::string& candidate,
const std::string& mdns_addr) {
test_utils_->sts_target()->Dispatch(
WrapRunnable(this, &IceTestPeer::ParseCandidate_s, i, candidate,
mdns_addr),
NS_DISPATCH_SYNC);
test_utils_->SyncDispatchToSTS(WrapRunnable(
this, &IceTestPeer::ParseCandidate_s, i, candidate, mdns_addr));
}
void DisableComponent_s(size_t index, int component_id) {
@ -1251,10 +1227,8 @@ class IceTestPeer : public sigslot::has_slots<> {
}
void DisableComponent(size_t stream, int component_id) {
test_utils_->sts_target()->Dispatch(
WrapRunnable(this, &IceTestPeer::DisableComponent_s, stream,
component_id),
NS_DISPATCH_SYNC);
test_utils_->SyncDispatchToSTS(WrapRunnable(
this, &IceTestPeer::DisableComponent_s, stream, component_id));
}
void AssertConsentRefresh_s(size_t index, int component_id,
@ -1288,9 +1262,8 @@ class IceTestPeer : public sigslot::has_slots<> {
}
void AssertConsentRefresh(ConsentStatus status) {
test_utils_->sts_target()->Dispatch(
WrapRunnable(this, &IceTestPeer::AssertConsentRefresh_s, 0, 1, status),
NS_DISPATCH_SYNC);
test_utils_->SyncDispatchToSTS(
WrapRunnable(this, &IceTestPeer::AssertConsentRefresh_s, 0, 1, status));
}
void ChangeNetworkState_s(bool online) {
@ -1298,31 +1271,27 @@ class IceTestPeer : public sigslot::has_slots<> {
}
void ChangeNetworkStateToOffline() {
test_utils_->sts_target()->Dispatch(
WrapRunnable(this, &IceTestPeer::ChangeNetworkState_s, false),
NS_DISPATCH_SYNC);
test_utils_->SyncDispatchToSTS(
WrapRunnable(this, &IceTestPeer::ChangeNetworkState_s, false));
}
void ChangeNetworkStateToOnline() {
test_utils_->sts_target()->Dispatch(
WrapRunnable(this, &IceTestPeer::ChangeNetworkState_s, true),
NS_DISPATCH_SYNC);
test_utils_->SyncDispatchToSTS(
WrapRunnable(this, &IceTestPeer::ChangeNetworkState_s, true));
}
void SetControlling(NrIceCtx::Controlling controlling) {
nsresult res;
test_utils_->sts_target()->Dispatch(
WrapRunnableRet(&res, ice_ctx_, &NrIceCtx::SetControlling, controlling),
NS_DISPATCH_SYNC);
test_utils_->SyncDispatchToSTS(WrapRunnableRet(
&res, ice_ctx_, &NrIceCtx::SetControlling, controlling));
ASSERT_TRUE(NS_SUCCEEDED(res));
}
NrIceCtx::Controlling GetControlling() { return ice_ctx_->GetControlling(); }
void SetTiebreaker(uint64_t tiebreaker) {
test_utils_->sts_target()->Dispatch(
WrapRunnable(this, &IceTestPeer::SetTiebreaker_s, tiebreaker),
NS_DISPATCH_SYNC);
test_utils_->SyncDispatchToSTS(
WrapRunnable(this, &IceTestPeer::SetTiebreaker_s, tiebreaker));
}
void SetTiebreaker_s(uint64_t tiebreaker) {
@ -1337,10 +1306,8 @@ class IceTestPeer : public sigslot::has_slots<> {
nsresult GetDefaultCandidate(unsigned int stream, NrIceCandidate* cand) {
nsresult rv;
test_utils_->sts_target()->Dispatch(
WrapRunnableRet(&rv, this, &IceTestPeer::GetDefaultCandidate_s, stream,
cand),
NS_DISPATCH_SYNC);
test_utils_->SyncDispatchToSTS(WrapRunnableRet(
&rv, this, &IceTestPeer::GetDefaultCandidate_s, stream, cand));
return rv;
}
@ -1396,15 +1363,11 @@ class WebRtcIceGatherTest : public StunTest {
Preferences::SetInt("media.peerconnection.ice.tcp_so_sock_count", 3);
test_utils_->sts_target()->Dispatch(
WrapRunnable(TestStunServer::GetInstance(AF_INET),
&TestStunServer::Reset),
NS_DISPATCH_SYNC);
test_utils_->SyncDispatchToSTS(WrapRunnable(
TestStunServer::GetInstance(AF_INET), &TestStunServer::Reset));
if (TestStunServer::GetInstance(AF_INET6)) {
test_utils_->sts_target()->Dispatch(
WrapRunnable(TestStunServer::GetInstance(AF_INET6),
&TestStunServer::Reset),
NS_DISPATCH_SYNC);
test_utils_->SyncDispatchToSTS(WrapRunnable(
TestStunServer::GetInstance(AF_INET6), &TestStunServer::Reset));
}
}
@ -1823,8 +1786,8 @@ class WebRtcIceConnectTest : public StunTest {
void ConnectThenDelete() {
p2_->Connect(p1_.get(), TRICKLE_NONE, false);
p1_->Connect(p2_.get(), TRICKLE_NONE, true);
test_utils_->sts_target()->Dispatch(
WrapRunnable(this, &WebRtcIceConnectTest::CloseP1), NS_DISPATCH_SYNC);
test_utils_->SyncDispatchToSTS(
WrapRunnable(this, &WebRtcIceConnectTest::CloseP1));
p2_->StartChecks();
// Wait to see if we crash
@ -1841,14 +1804,13 @@ class WebRtcIceConnectTest : public StunTest {
size_t previousReceived = p2->received();
if (expect_tx_failure) {
test_utils_->sts_target()->Dispatch(
WrapRunnable(p1, &IceTestPeer::SendFailure, 0, 1), NS_DISPATCH_SYNC);
test_utils_->SyncDispatchToSTS(
WrapRunnable(p1, &IceTestPeer::SendFailure, 0, 1));
ASSERT_EQ(previousSent, p1->sent());
} else {
test_utils_->sts_target()->Dispatch(
test_utils_->SyncDispatchToSTS(
WrapRunnable(p1, &IceTestPeer::SendPacket, 0, 1,
reinterpret_cast<const unsigned char*>("TEST"), 4),
NS_DISPATCH_SYNC);
reinterpret_cast<const unsigned char*>("TEST"), 4));
ASSERT_EQ(previousSent + 1, p1->sent());
}
if (expect_rx_failure) {
@ -1860,9 +1822,8 @@ class WebRtcIceConnectTest : public StunTest {
}
void SendFailure() {
test_utils_->sts_target()->Dispatch(
WrapRunnable(p1_.get(), &IceTestPeer::SendFailure, 0, 1),
NS_DISPATCH_SYNC);
test_utils_->SyncDispatchToSTS(
WrapRunnable(p1_.get(), &IceTestPeer::SendFailure, 0, 1));
}
protected:
@ -1951,9 +1912,8 @@ class WebRtcIcePacketFilterTest : public StunTest {
}
void TearDown() {
test_utils_->sts_target()->Dispatch(
WrapRunnable(this, &WebRtcIcePacketFilterTest::TearDown_s),
NS_DISPATCH_SYNC);
test_utils_->SyncDispatchToSTS(
WrapRunnable(this, &WebRtcIcePacketFilterTest::TearDown_s));
StunTest::TearDown();
}

View file

@ -15,6 +15,7 @@
#include "nsISerialEventTarget.h"
#include "nsPISocketTransportService.h"
#include "nsServiceManagerUtils.h"
#include "nsThreadUtils.h"
class MtransportTestUtils {
public:
@ -32,6 +33,15 @@ class MtransportTestUtils {
nsISerialEventTarget* sts_target() { return sts_target_; }
nsresult SyncDispatchToSTS(nsIRunnable* aRunnable) {
return SyncDispatchToSTS(do_AddRef(aRunnable));
}
nsresult SyncDispatchToSTS(already_AddRefed<nsIRunnable>&& aRunnable) {
return NS_DispatchAndSpinEventLoopUntilComplete(
"MtransportTestUtils::SyncDispatchToSts"_ns, sts_target_,
std::move(aRunnable));
}
private:
nsCOMPtr<nsISerialEventTarget> sts_target_;
nsCOMPtr<nsPISocketTransportService> sts_;

View file

@ -41,17 +41,15 @@ class MultiTcpSocketTest : public MtransportTest {
NrIceCtx::InitializeGlobals(NrIceCtx::GlobalConfig());
ice_ctx_ = NrIceCtx::Create("stun");
test_utils_->sts_target()->Dispatch(
WrapRunnableNM(&TestStunTcpServer::GetInstance, AF_INET),
NS_DISPATCH_SYNC);
test_utils_->sts_target()->Dispatch(
WrapRunnableNM(&TestStunTcpServer::GetInstance, AF_INET6),
NS_DISPATCH_SYNC);
test_utils_->SyncDispatchToSTS(
WrapRunnableNM(&TestStunTcpServer::GetInstance, AF_INET));
test_utils_->SyncDispatchToSTS(
WrapRunnableNM(&TestStunTcpServer::GetInstance, AF_INET6));
}
void TearDown() {
test_utils_->sts_target()->Dispatch(
WrapRunnable(this, &MultiTcpSocketTest::Shutdown_s), NS_DISPATCH_SYNC);
test_utils_->SyncDispatchToSTS(
WrapRunnable(this, &MultiTcpSocketTest::Shutdown_s));
MtransportTest::TearDown();
}
@ -121,10 +119,9 @@ class MultiTcpSocketTest : public MtransportTest {
std::string stun_server_addr = "",
uint16_t stun_server_port = 0) {
nr_socket* sock = nullptr;
test_utils_->sts_target()->Dispatch(
test_utils_->SyncDispatchToSTS(
WrapRunnable(this, &MultiTcpSocketTest::Create_s, tcp_type,
stun_server_addr, stun_server_port, &sock),
NS_DISPATCH_SYNC);
stun_server_addr, stun_server_port, &sock));
return sock;
}
@ -138,9 +135,8 @@ class MultiTcpSocketTest : public MtransportTest {
}
void Listen(nr_socket* sock) {
test_utils_->sts_target()->Dispatch(
WrapRunnable(this, &MultiTcpSocketTest::Listen_s, sock),
NS_DISPATCH_SYNC);
test_utils_->SyncDispatchToSTS(
WrapRunnable(this, &MultiTcpSocketTest::Listen_s, sock));
}
void Destroy_s(nr_socket* sock) {
@ -149,9 +145,8 @@ class MultiTcpSocketTest : public MtransportTest {
}
void Destroy(nr_socket* sock) {
test_utils_->sts_target()->Dispatch(
WrapRunnable(this, &MultiTcpSocketTest::Destroy_s, sock),
NS_DISPATCH_SYNC);
test_utils_->SyncDispatchToSTS(
WrapRunnable(this, &MultiTcpSocketTest::Destroy_s, sock));
}
void Connect_s(nr_socket* from, nr_socket* to) {
@ -168,9 +163,8 @@ class MultiTcpSocketTest : public MtransportTest {
}
void Connect(nr_socket* from, nr_socket* to) {
test_utils_->sts_target()->Dispatch(
WrapRunnable(this, &MultiTcpSocketTest::Connect_s, from, to),
NS_DISPATCH_SYNC);
test_utils_->SyncDispatchToSTS(
WrapRunnable(this, &MultiTcpSocketTest::Connect_s, from, to));
}
void ConnectSo_s(nr_socket* so1, nr_socket* so2) {
@ -188,9 +182,8 @@ class MultiTcpSocketTest : public MtransportTest {
}
void ConnectSo(nr_socket* from, nr_socket* to) {
test_utils_->sts_target()->Dispatch(
WrapRunnable(this, &MultiTcpSocketTest::ConnectSo_s, from, to),
NS_DISPATCH_SYNC);
test_utils_->SyncDispatchToSTS(
WrapRunnable(this, &MultiTcpSocketTest::ConnectSo_s, from, to));
}
void SendDataToAddress_s(nr_socket* from, nr_transport_addr* to,
@ -207,10 +200,8 @@ class MultiTcpSocketTest : public MtransportTest {
void SendData(nr_socket* from, nr_transport_addr* to, const char* data,
size_t len) {
test_utils_->sts_target()->Dispatch(
WrapRunnable(this, &MultiTcpSocketTest::SendDataToAddress_s, from, to,
data, len),
NS_DISPATCH_SYNC);
test_utils_->SyncDispatchToSTS(WrapRunnable(
this, &MultiTcpSocketTest::SendDataToAddress_s, from, to, data, len));
}
void SendDataToSocket_s(nr_socket* from, nr_socket* to, const char* data,
@ -223,10 +214,8 @@ class MultiTcpSocketTest : public MtransportTest {
}
void SendData(nr_socket* from, nr_socket* to, const char* data, size_t len) {
test_utils_->sts_target()->Dispatch(
WrapRunnable(this, &MultiTcpSocketTest::SendDataToSocket_s, from, to,
data, len),
NS_DISPATCH_SYNC);
test_utils_->SyncDispatchToSTS(WrapRunnable(
this, &MultiTcpSocketTest::SendDataToSocket_s, from, to, data, len));
}
void RecvDataFromAddress_s(nr_transport_addr* expected_from,
@ -262,10 +251,9 @@ class MultiTcpSocketTest : public MtransportTest {
void RecvData(nr_transport_addr* expected_from, nr_socket* sent_to,
const char* expected_data = nullptr, size_t expected_len = 0) {
ASSERT_TRUE_WAIT(IsReadable(), 1000);
test_utils_->sts_target()->Dispatch(
test_utils_->SyncDispatchToSTS(
WrapRunnable(this, &MultiTcpSocketTest::RecvDataFromAddress_s,
expected_from, sent_to, expected_data, expected_len),
NS_DISPATCH_SYNC);
expected_from, sent_to, expected_data, expected_len));
}
void RecvDataFromSocket_s(nr_socket* expected_from, nr_socket* sent_to,
@ -281,10 +269,9 @@ class MultiTcpSocketTest : public MtransportTest {
void RecvData(nr_socket* expected_from, nr_socket* sent_to,
const char* expected_data, size_t expected_len) {
ASSERT_TRUE_WAIT(IsReadable(), 1000);
test_utils_->sts_target()->Dispatch(
test_utils_->SyncDispatchToSTS(
WrapRunnable(this, &MultiTcpSocketTest::RecvDataFromSocket_s,
expected_from, sent_to, expected_data, expected_len),
NS_DISPATCH_SYNC);
expected_from, sent_to, expected_data, expected_len));
}
void RecvDataFailed_s(nr_socket* sent_to, size_t expected_len,
@ -306,10 +293,9 @@ class MultiTcpSocketTest : public MtransportTest {
void RecvDataFailed(nr_socket* sent_to, size_t expected_len,
int expected_err) {
ASSERT_TRUE_WAIT(IsReadable(), 1000);
test_utils_->sts_target()->Dispatch(
test_utils_->SyncDispatchToSTS(
WrapRunnable(this, &MultiTcpSocketTest::RecvDataFailed_s, sent_to,
expected_len, expected_err),
NS_DISPATCH_SYNC);
expected_len, expected_err));
}
void TransferData(nr_socket* from, nr_socket* to, const char* data,

View file

@ -32,9 +32,8 @@ class TimerTest : public MtransportTest {
int ArmTimer(int timeout) {
int ret;
test_utils_->sts_target()->Dispatch(
WrapRunnableRet(&ret, this, &TimerTest::ArmTimer_w, timeout),
NS_DISPATCH_SYNC);
test_utils_->SyncDispatchToSTS(
WrapRunnableRet(&ret, this, &TimerTest::ArmTimer_w, timeout));
return ret;
}
@ -42,9 +41,8 @@ class TimerTest : public MtransportTest {
int ArmCancelTimer(int timeout) {
int ret;
test_utils_->sts_target()->Dispatch(
WrapRunnableRet(&ret, this, &TimerTest::ArmCancelTimer_w, timeout),
NS_DISPATCH_SYNC);
test_utils_->SyncDispatchToSTS(
WrapRunnableRet(&ret, this, &TimerTest::ArmCancelTimer_w, timeout));
return ret;
}
@ -64,9 +62,8 @@ class TimerTest : public MtransportTest {
int CancelTimer() {
int ret;
test_utils_->sts_target()->Dispatch(
WrapRunnableRet(&ret, this, &TimerTest::CancelTimer_w),
NS_DISPATCH_SYNC);
test_utils_->SyncDispatchToSTS(
WrapRunnableRet(&ret, this, &TimerTest::CancelTimer_w));
return ret;
}
@ -76,8 +73,8 @@ class TimerTest : public MtransportTest {
int Schedule() {
int ret;
test_utils_->sts_target()->Dispatch(
WrapRunnableRet(&ret, this, &TimerTest::Schedule_w), NS_DISPATCH_SYNC);
test_utils_->SyncDispatchToSTS(
WrapRunnableRet(&ret, this, &TimerTest::Schedule_w));
return ret;
}

View file

@ -161,20 +161,23 @@ class DispatchTest : public MtransportTest {
void Test1Arg() {
Runnable* r = WrapRunnable(&cl_, &TargetClass::m1, 1);
target_->Dispatch(r, NS_DISPATCH_SYNC);
NS_DispatchAndSpinEventLoopUntilComplete("DispatchTest::Test1Arg"_ns,
target_, do_AddRef(r));
ASSERT_EQ(1, ran_);
}
void Test2Args() {
Runnable* r = WrapRunnable(&cl_, &TargetClass::m2, 1, 2);
target_->Dispatch(r, NS_DISPATCH_SYNC);
NS_DispatchAndSpinEventLoopUntilComplete("DispatchTest::Test2Args"_ns,
target_, do_AddRef(r));
ASSERT_EQ(2, ran_);
}
void Test1Set() {
bool x = false;
target_->Dispatch(WrapRunnable(&cl_, &TargetClass::m1set, &x),
NS_DISPATCH_SYNC);
NS_DispatchAndSpinEventLoopUntilComplete(
"DispatchTest::Test1Set"_ns, target_,
do_AddRef(WrapRunnable(&cl_, &TargetClass::m1set, &x)));
ASSERT_TRUE(x);
}
@ -182,8 +185,9 @@ class DispatchTest : public MtransportTest {
int z;
int x = 10;
target_->Dispatch(WrapRunnableRet(&z, &cl_, &TargetClass::return_int, x),
NS_DISPATCH_SYNC);
NS_DispatchAndSpinEventLoopUntilComplete(
"DispatchTest::TestRet"_ns, target_,
do_AddRef(WrapRunnableRet(&z, &cl_, &TargetClass::return_int, x)));
ASSERT_EQ(10, z);
}
@ -214,8 +218,7 @@ int SetNonMethodRet(TargetClass* cl, int x) {
}
TEST_F(DispatchTest, TestNonMethod) {
test_utils_->sts_target()->Dispatch(WrapRunnableNM(SetNonMethod, &cl_, 10),
NS_DISPATCH_SYNC);
test_utils_->SyncDispatchToSTS(WrapRunnableNM(SetNonMethod, &cl_, 10));
ASSERT_EQ(1, ran_);
}
@ -223,8 +226,8 @@ TEST_F(DispatchTest, TestNonMethod) {
TEST_F(DispatchTest, TestNonMethodRet) {
int z;
test_utils_->sts_target()->Dispatch(
WrapRunnableNMRet(&z, SetNonMethodRet, &cl_, 10), NS_DISPATCH_SYNC);
test_utils_->SyncDispatchToSTS(
WrapRunnableNMRet(&z, SetNonMethodRet, &cl_, 10));
ASSERT_EQ(1, ran_);
ASSERT_EQ(10, z);
@ -234,9 +237,10 @@ TEST_F(DispatchTest, TestDestructorRef) {
bool destroyed = false;
{
RefPtr<Destructor> destructor = new Destructor(&destroyed);
target_->Dispatch(
WrapRunnable(&cl_, &TargetClass::destructor_target_ref, destructor),
NS_DISPATCH_SYNC);
NS_DispatchAndSpinEventLoopUntilComplete(
"DispatchTest::TestDestructorRef"_ns, target_,
do_AddRef(WrapRunnable(&cl_, &TargetClass::destructor_target_ref,
destructor)));
ASSERT_FALSE(destroyed);
}
ASSERT_TRUE(destroyed);
@ -245,9 +249,10 @@ TEST_F(DispatchTest, TestDestructorRef) {
destroyed = false;
{
RefPtr<Destructor> destructor = new Destructor(&destroyed);
target_->Dispatch(WrapRunnable(&cl_, &TargetClass::destructor_target_ref,
std::move(destructor)),
NS_DISPATCH_SYNC);
NS_DispatchAndSpinEventLoopUntilComplete(
"DispatchTest::TestDestructorRef"_ns, target_,
do_AddRef(WrapRunnable(&cl_, &TargetClass::destructor_target_ref,
std::move(destructor))));
ASSERT_TRUE(destroyed);
}
}
@ -261,8 +266,9 @@ TEST_F(DispatchTest, TestMove) {
// - moved arg
// - by-val capture in function should consume a move
// - expect destruction in the function scope
target_->Dispatch(WrapRunnableNM([](CtorDtorState s) {}, std::move(state)),
NS_DISPATCH_SYNC);
NS_DispatchAndSpinEventLoopUntilComplete(
"DispatchTest::TestMove"_ns, target_,
do_AddRef(WrapRunnableNM([](CtorDtorState s) {}, std::move(state))));
ASSERT_EQ(1, destroyed);
}
// Still shouldn't count when we go out of scope as it was moved.
@ -275,8 +281,9 @@ TEST_F(DispatchTest, TestMove) {
// - copied arg
// - by-val capture in function should consume a move
// - expect destruction in the function scope and call scope
target_->Dispatch(WrapRunnableNM([](CtorDtorState s) {}, state),
NS_DISPATCH_SYNC);
NS_DispatchAndSpinEventLoopUntilComplete(
"DispatchTest::TestMove"_ns, target_,
do_AddRef(WrapRunnableNM([](CtorDtorState s) {}, state)));
ASSERT_EQ(2, destroyed);
}
// Original state should be destroyed
@ -289,9 +296,10 @@ TEST_F(DispatchTest, TestMove) {
// - moved arg
// - by-ref in function should accept a moved arg
// - expect destruction in the wrapper invocation scope
target_->Dispatch(
WrapRunnableNM([](const CtorDtorState& s) {}, std::move(state)),
NS_DISPATCH_SYNC);
NS_DispatchAndSpinEventLoopUntilComplete(
"DispatchTest::TestMove"_ns, target_,
do_AddRef(
WrapRunnableNM([](const CtorDtorState& s) {}, std::move(state))));
ASSERT_EQ(4, destroyed);
}
// Still shouldn't count when we go out of scope as it was moved.
@ -304,9 +312,9 @@ TEST_F(DispatchTest, TestMove) {
// - moved arg
// - r-value function should accept a moved arg
// - expect destruction in the wrapper invocation scope
target_->Dispatch(
WrapRunnableNM([](CtorDtorState&& s) {}, std::move(state)),
NS_DISPATCH_SYNC);
NS_DispatchAndSpinEventLoopUntilComplete(
"DispatchTest::TestMove"_ns, target_,
do_AddRef(WrapRunnableNM([](CtorDtorState&& s) {}, std::move(state))));
ASSERT_EQ(5, destroyed);
}
// Still shouldn't count when we go out of scope as it was moved.
@ -318,8 +326,9 @@ TEST_F(DispatchTest, TestUniquePtr) {
int ran = 0;
auto cl = MakeUnique<TargetClass>(&ran);
target_->Dispatch(WrapRunnable(std::move(cl), &TargetClass::m1, 1),
NS_DISPATCH_SYNC);
NS_DispatchAndSpinEventLoopUntilComplete(
"DispatchTest::TestUniquePtr"_ns, target_,
do_AddRef(WrapRunnable(std::move(cl), &TargetClass::m1, 1)));
ASSERT_EQ(1, ran);
// Test that UniquePtr works as a param to the runnable
@ -331,9 +340,10 @@ TEST_F(DispatchTest, TestUniquePtr) {
// - moved arg
// - Function should move construct from arg
// - expect destruction in the wrapper invocation scope
target_->Dispatch(
WrapRunnableNM([](UniquePtr<CtorDtorState> s) {}, std::move(state)),
NS_DISPATCH_SYNC);
NS_DispatchAndSpinEventLoopUntilComplete(
"DispatchTest::TestUniquePtr"_ns, target_,
do_AddRef(WrapRunnableNM([](UniquePtr<CtorDtorState> s) {},
std::move(state))));
ASSERT_EQ(1, destroyed);
}
// Still shouldn't count when we go out of scope as it was moved.

View file

@ -119,16 +119,15 @@ class TransportTestPeer : public sigslot::has_slots<> {
usrsctp_close(sctp_);
usrsctp_deregister_address(static_cast<void*>(this));
test_utils_->sts_target()->Dispatch(
WrapRunnable(this, &TransportTestPeer::Disconnect_s), NS_DISPATCH_SYNC);
test_utils_->SyncDispatchToSTS(
WrapRunnable(this, &TransportTestPeer::Disconnect_s));
std::cerr << "~TransportTestPeer() completed" << std::endl;
}
void ConnectSocket(TransportTestPeer* peer) {
test_utils_->sts_target()->Dispatch(
WrapRunnable(this, &TransportTestPeer::ConnectSocket_s, peer),
NS_DISPATCH_SYNC);
test_utils_->SyncDispatchToSTS(
WrapRunnable(this, &TransportTestPeer::ConnectSocket_s, peer));
}
void ConnectSocket_s(TransportTestPeer* peer) {

View file

@ -108,8 +108,7 @@ class IcePeer {
virtual ~IcePeer() { Destroy(); }
void Destroy() {
test_utils_->sts_target()->Dispatch(WrapRunnable(this, &IcePeer::Destroy_s),
NS_DISPATCH_SYNC);
test_utils_->SyncDispatchToSTS(WrapRunnable(this, &IcePeer::Destroy_s));
}
void Destroy_s() {
@ -120,9 +119,8 @@ class IcePeer {
}
void Gather(bool default_route_only = false) {
test_utils_->sts_target()->Dispatch(
WrapRunnable(this, &IcePeer::Gather_s, default_route_only),
NS_DISPATCH_SYNC);
test_utils_->SyncDispatchToSTS(
WrapRunnable(this, &IcePeer::Gather_s, default_route_only));
}
void Gather_s(bool default_route_only = false) {
@ -132,9 +130,8 @@ class IcePeer {
std::vector<std::string> GetStreamAttributes() {
std::vector<std::string> attributes;
test_utils_->sts_target()->Dispatch(
WrapRunnableRet(&attributes, this, &IcePeer::GetStreamAttributes_s),
NS_DISPATCH_SYNC);
test_utils_->SyncDispatchToSTS(
WrapRunnableRet(&attributes, this, &IcePeer::GetStreamAttributes_s));
return attributes;
}
@ -158,9 +155,8 @@ class IcePeer {
std::vector<std::string> GetGlobalAttributes() {
std::vector<std::string> attributes;
test_utils_->sts_target()->Dispatch(
WrapRunnableRet(&attributes, this, &IcePeer::GetGlobalAttributes_s),
NS_DISPATCH_SYNC);
test_utils_->SyncDispatchToSTS(
WrapRunnableRet(&attributes, this, &IcePeer::GetGlobalAttributes_s));
return attributes;
}
@ -197,9 +193,8 @@ class IcePeer {
}
void SetRemoteAttributes(std::vector<std::string> attributes) {
test_utils_->sts_target()->Dispatch(
WrapRunnable(this, &IcePeer::SetRemoteAttributes_s, attributes),
NS_DISPATCH_SYNC);
test_utils_->SyncDispatchToSTS(
WrapRunnable(this, &IcePeer::SetRemoteAttributes_s, attributes));
}
void SetRemoteAttributes_s(std::vector<std::string> attributes) {
@ -219,8 +214,7 @@ class IcePeer {
}
void StartChecks() {
test_utils_->sts_target()->Dispatch(
WrapRunnable(this, &IcePeer::StartChecks_s), NS_DISPATCH_SYNC);
test_utils_->SyncDispatchToSTS(WrapRunnable(this, &IcePeer::StartChecks_s));
}
void StartChecks_s() {

View file

@ -50,8 +50,7 @@ class TestNrSocketTest : public MtransportTest {
}
void TearDown() override {
sts_->Dispatch(WrapRunnable(this, &TestNrSocketTest::TearDown_s),
NS_DISPATCH_SYNC);
SyncDispatchToSTS(WrapRunnable(this, &TestNrSocketTest::TearDown_s));
MtransportTest::TearDown();
}
@ -79,9 +78,8 @@ class TestNrSocketTest : public MtransportTest {
void CreatePublicAddrs(size_t count, const char* ip_str = "127.0.0.1",
int proto = IPPROTO_UDP) {
sts_->Dispatch(WrapRunnable(this, &TestNrSocketTest::CreatePublicAddrs_s,
count, ip_str, proto),
NS_DISPATCH_SYNC);
SyncDispatchToSTS(WrapRunnable(this, &TestNrSocketTest::CreatePublicAddrs_s,
count, ip_str, proto));
}
void CreatePublicAddrs_s(size_t count, const char* ip_str, int proto) {
@ -97,10 +95,9 @@ class TestNrSocketTest : public MtransportTest {
const char* ip_str = "127.0.0.1",
int proto = IPPROTO_UDP) {
RefPtr<TestNat> result;
sts_->Dispatch(
WrapRunnableRet(&result, this, &TestNrSocketTest::CreatePrivateAddrs_s,
size, ip_str, proto),
NS_DISPATCH_SYNC);
SyncDispatchToSTS(WrapRunnableRet(&result, this,
&TestNrSocketTest::CreatePrivateAddrs_s,
size, ip_str, proto));
return result;
}
@ -130,9 +127,8 @@ class TestNrSocketTest : public MtransportTest {
}
int result = 0;
sts_->Dispatch(WrapRunnableRet(&result, this, &TestNrSocketTest::SendData_s,
from, via),
NS_DISPATCH_SYNC);
SyncDispatchToSTS(WrapRunnableRet(
&result, this, &TestNrSocketTest::SendData_s, from, via));
if (result) {
return false;
}
@ -147,9 +143,9 @@ class TestNrSocketTest : public MtransportTest {
}
MOZ_ASSERT(to);
sts_->Dispatch(WrapRunnableRet(&result, this, &TestNrSocketTest::RecvData_s,
to, sender_external_address),
NS_DISPATCH_SYNC);
SyncDispatchToSTS(WrapRunnableRet(&result, this,
&TestNrSocketTest::RecvData_s, to,
sender_external_address));
return !result;
}
@ -180,9 +176,8 @@ class TestNrSocketTest : public MtransportTest {
}
int r;
sts_->Dispatch(
WrapRunnableRet(&r, this, &TestNrSocketTest::SendDataTcp_s, from),
NS_DISPATCH_SYNC);
SyncDispatchToSTS(
WrapRunnableRet(&r, this, &TestNrSocketTest::SendDataTcp_s, from));
if (r) {
std::cerr << "SendDataTcp_s (1) failed" << std::endl;
return false;
@ -193,9 +188,8 @@ class TestNrSocketTest : public MtransportTest {
return false;
}
sts_->Dispatch(WrapRunnableRet(&r, this, &TestNrSocketTest::RecvDataTcp_s,
accepted_sock),
NS_DISPATCH_SYNC);
SyncDispatchToSTS(WrapRunnableRet(
&r, this, &TestNrSocketTest::RecvDataTcp_s, accepted_sock));
if (r) {
std::cerr << "RecvDataTcp_s (1) failed" << std::endl;
return false;
@ -206,9 +200,8 @@ class TestNrSocketTest : public MtransportTest {
return false;
}
sts_->Dispatch(WrapRunnableRet(&r, this, &TestNrSocketTest::SendDataTcp_s,
accepted_sock),
NS_DISPATCH_SYNC);
SyncDispatchToSTS(WrapRunnableRet(
&r, this, &TestNrSocketTest::SendDataTcp_s, accepted_sock));
if (r) {
std::cerr << "SendDataTcp_s (2) failed" << std::endl;
return false;
@ -219,9 +212,8 @@ class TestNrSocketTest : public MtransportTest {
return false;
}
sts_->Dispatch(
WrapRunnableRet(&r, this, &TestNrSocketTest::RecvDataTcp_s, from),
NS_DISPATCH_SYNC);
SyncDispatchToSTS(
WrapRunnableRet(&r, this, &TestNrSocketTest::RecvDataTcp_s, from));
if (r) {
std::cerr << "RecvDataTcp_s (2) failed" << std::endl;
return false;
@ -234,9 +226,8 @@ class TestNrSocketTest : public MtransportTest {
MOZ_ASSERT(sock);
MOZ_ASSERT(address);
int r;
sts_->Dispatch(WrapRunnableRet(&r, this, &TestNrSocketTest::GetAddress_s,
sock, address),
NS_DISPATCH_SYNC);
SyncDispatchToSTS(WrapRunnableRet(&r, this, &TestNrSocketTest::GetAddress_s,
sock, address));
return r;
}
@ -321,16 +312,15 @@ class TestNrSocketTest : public MtransportTest {
bool Connect(TestNrSocket* from, TestNrSocket* to,
NrSocketBase** accepted_sock) {
int r;
sts_->Dispatch(WrapRunnableRet(&r, this, &TestNrSocketTest::Listen_s, to),
NS_DISPATCH_SYNC);
SyncDispatchToSTS(
WrapRunnableRet(&r, this, &TestNrSocketTest::Listen_s, to));
if (r) {
std::cerr << "Listen_s failed: " << r << std::endl;
return false;
}
sts_->Dispatch(
WrapRunnableRet(&r, this, &TestNrSocketTest::Connect_s, from, to),
NS_DISPATCH_SYNC);
SyncDispatchToSTS(
WrapRunnableRet(&r, this, &TestNrSocketTest::Connect_s, from, to));
if (r && r != R_WOULDBLOCK) {
std::cerr << "Connect_s failed: " << r << std::endl;
return false;
@ -341,9 +331,8 @@ class TestNrSocketTest : public MtransportTest {
return false;
}
sts_->Dispatch(WrapRunnableRet(&r, this, &TestNrSocketTest::Accept_s, to,
accepted_sock),
NS_DISPATCH_SYNC);
SyncDispatchToSTS(WrapRunnableRet(&r, this, &TestNrSocketTest::Accept_s, to,
accepted_sock));
if (r) {
std::cerr << "Accept_s failed: " << r << std::endl;
@ -354,18 +343,16 @@ class TestNrSocketTest : public MtransportTest {
bool WaitForSocketState(NrSocketBase* sock, int state) {
MOZ_ASSERT(sock);
sts_->Dispatch(WrapRunnable(this, &TestNrSocketTest::WaitForSocketState_s,
sock, state),
NS_DISPATCH_SYNC);
SyncDispatchToSTS(WrapRunnable(
this, &TestNrSocketTest::WaitForSocketState_s, sock, state));
bool res;
WAIT_(wait_done_for_main_, 500, res);
wait_done_for_main_ = false;
if (!res) {
sts_->Dispatch(
WrapRunnable(this, &TestNrSocketTest::CancelWait_s, sock, state),
NS_DISPATCH_SYNC);
SyncDispatchToSTS(
WrapRunnable(this, &TestNrSocketTest::CancelWait_s, sock, state));
}
return res;
@ -385,6 +372,11 @@ class TestNrSocketTest : public MtransportTest {
return WaitForSocketState(sock, NR_ASYNC_WAIT_WRITE);
}
void SyncDispatchToSTS(nsIRunnable* runnable) {
NS_DispatchAndSpinEventLoopUntilComplete(
"TestNrSocketTest::SyncDispatchToSTS"_ns, sts_, do_AddRef(runnable));
}
static void WaitDone(void* sock, int how, void* test_fixture) {
TestNrSocketTest* test = static_cast<TestNrSocketTest*>(test_fixture);
test->wait_done_for_main_ = true;

View file

@ -466,8 +466,8 @@ class TransportTestPeer : public sigslot::has_slots<> {
}
~TransportTestPeer() {
test_utils_->sts_target()->Dispatch(
WrapRunnable(this, &TransportTestPeer::DestroyFlow), NS_DISPATCH_SYNC);
test_utils_->SyncDispatchToSTS(
WrapRunnable(this, &TransportTestPeer::DestroyFlow));
}
void DestroyFlow() {
@ -482,15 +482,11 @@ class TransportTestPeer : public sigslot::has_slots<> {
}
void DisconnectDestroyFlow() {
test_utils_->sts_target()->Dispatch(
NS_NewRunnableFunction(
__func__,
[this] {
loopback_->Disconnect();
disconnect_all(); // Disconnect from the signals;
flow_ = nullptr;
}),
NS_DISPATCH_SYNC);
test_utils_->SyncDispatchToSTS(NS_NewRunnableFunction(__func__, [this] {
loopback_->Disconnect();
disconnect_all(); // Disconnect from the signals;
flow_ = nullptr;
}));
}
void SetDtlsAllowAll() {
@ -577,9 +573,8 @@ class TransportTestPeer : public sigslot::has_slots<> {
}
void ConnectSocket(TransportTestPeer* peer) {
RUN_ON_THREAD(test_utils_->sts_target(),
WrapRunnable(this, &TransportTestPeer::ConnectSocket_s, peer),
NS_DISPATCH_SYNC);
test_utils_->SyncDispatchToSTS(
WrapRunnable(this, &TransportTestPeer::ConnectSocket_s, peer));
}
nsresult InitIce_s() {
@ -618,9 +613,8 @@ class TransportTestPeer : public sigslot::has_slots<> {
ice_ = new TransportLayerIce();
ice_->SetParameters(stream, 1);
test_utils_->sts_target()->Dispatch(
WrapRunnableRet(&res, this, &TransportTestPeer::InitIce_s),
NS_DISPATCH_SYNC);
test_utils_->SyncDispatchToSTS(
WrapRunnableRet(&res, this, &TransportTestPeer::InitIce_s));
ASSERT_EQ((nsresult)NS_OK, res);
@ -630,10 +624,8 @@ class TransportTestPeer : public sigslot::has_slots<> {
dtls_->SignalStateChange.connect(this, &TransportTestPeer::StateChanged);
// Start gathering
test_utils_->sts_target()->Dispatch(
WrapRunnableRet(&res, ice_ctx_, &NrIceCtx::StartGathering, false,
false),
NS_DISPATCH_SYNC);
test_utils_->SyncDispatchToSTS(WrapRunnableRet(
&res, ice_ctx_, &NrIceCtx::StartGathering, false, false));
ASSERT_TRUE(NS_SUCCEEDED(res));
}
@ -671,26 +663,22 @@ class TransportTestPeer : public sigslot::has_slots<> {
}
// First send attributes
test_utils_->sts_target()->Dispatch(
test_utils_->SyncDispatchToSTS(
WrapRunnableRet(&res, peer_->ice_ctx_, &NrIceCtx::ParseGlobalAttributes,
ice_ctx_->GetGlobalAttributes()),
NS_DISPATCH_SYNC);
ice_ctx_->GetGlobalAttributes()));
ASSERT_TRUE(NS_SUCCEEDED(res));
for (size_t i = 0; i < streams_.size(); ++i) {
test_utils_->sts_target()->Dispatch(
WrapRunnableRet(&res, peer_->streams_[i],
&NrIceMediaStream::ConnectToPeer, "ufrag", "pass",
streams_[i]->GetAttributes()),
NS_DISPATCH_SYNC);
test_utils_->SyncDispatchToSTS(WrapRunnableRet(
&res, peer_->streams_[i], &NrIceMediaStream::ConnectToPeer, "ufrag",
"pass", streams_[i]->GetAttributes()));
ASSERT_TRUE(NS_SUCCEEDED(res));
}
// Start checks on the other peer.
test_utils_->sts_target()->Dispatch(
WrapRunnableRet(&res, peer_->ice_ctx_, &NrIceCtx::StartChecks),
NS_DISPATCH_SYNC);
test_utils_->SyncDispatchToSTS(
WrapRunnableRet(&res, peer_->ice_ctx_, &NrIceCtx::StartChecks));
ASSERT_TRUE(NS_SUCCEEDED(res));
}
@ -704,10 +692,8 @@ class TransportTestPeer : public sigslot::has_slots<> {
TransportResult SendPacket(MediaPacket& packet) {
TransportResult ret;
test_utils_->sts_target()->Dispatch(
WrapRunnableNMRet(&ret, &TransportTestPeer::SendPacketWrapper, dtls_,
&packet),
NS_DISPATCH_SYNC);
test_utils_->SyncDispatchToSTS(WrapRunnableNMRet(
&ret, &TransportTestPeer::SendPacketWrapper, dtls_, &packet));
return ret;
}
@ -940,12 +926,10 @@ class TransportTest : public MtransportTest {
protected:
void ConnectSocketInternal() {
test_utils_->sts_target()->Dispatch(
WrapRunnable(p1_, &TransportTestPeer::ConnectSocket, p2_),
NS_DISPATCH_SYNC);
test_utils_->sts_target()->Dispatch(
WrapRunnable(p2_, &TransportTestPeer::ConnectSocket, p1_),
NS_DISPATCH_SYNC);
test_utils_->SyncDispatchToSTS(
WrapRunnable(p1_, &TransportTestPeer::ConnectSocket, p2_));
test_utils_->SyncDispatchToSTS(
WrapRunnable(p2_, &TransportTestPeer::ConnectSocket, p1_));
}
PRFileDesc* fds_[2];

View file

@ -135,9 +135,7 @@ class TurnClient : public MtransportTest {
}
void TearDown() {
RUN_ON_THREAD(test_utils_->sts_target(),
WrapRunnable(this, &TurnClient::TearDown_s),
NS_DISPATCH_SYNC);
test_utils_->SyncDispatchToSTS(WrapRunnable(this, &TurnClient::TearDown_s));
}
void Allocate_s() {
@ -149,9 +147,7 @@ class TurnClient : public MtransportTest {
}
void Allocate(bool expect_success = true) {
RUN_ON_THREAD(test_utils_->sts_target(),
WrapRunnable(this, &TurnClient::Allocate_s),
NS_DISPATCH_SYNC);
test_utils_->SyncDispatchToSTS(WrapRunnable(this, &TurnClient::Allocate_s));
if (expect_success) {
ASSERT_TRUE_WAIT(allocated_, 5000);
@ -188,9 +184,8 @@ class TurnClient : public MtransportTest {
}
void Deallocate() {
RUN_ON_THREAD(test_utils_->sts_target(),
WrapRunnable(this, &TurnClient::Deallocate_s),
NS_DISPATCH_SYNC);
test_utils_->SyncDispatchToSTS(
WrapRunnable(this, &TurnClient::Deallocate_s));
}
void RequestPermission_s(const std::string& target) {
@ -215,9 +210,8 @@ class TurnClient : public MtransportTest {
}
void RequestPermission(const std::string& target) {
RUN_ON_THREAD(test_utils_->sts_target(),
WrapRunnable(this, &TurnClient::RequestPermission_s, target),
NS_DISPATCH_SYNC);
test_utils_->SyncDispatchToSTS(
WrapRunnable(this, &TurnClient::RequestPermission_s, target));
}
void Readable(NR_SOCKET s, int how, void* arg) {
@ -305,10 +299,8 @@ class TurnClient : public MtransportTest {
}
void SendTo(const std::string& target, int expect_return = 0) {
RUN_ON_THREAD(
test_utils_->sts_target(),
WrapRunnable(this, &TurnClient::SendTo_s, target, expect_return),
NS_DISPATCH_SYNC);
test_utils_->SyncDispatchToSTS(
WrapRunnable(this, &TurnClient::SendTo_s, target, expect_return));
}
int received() const { return received_; }

View file

@ -293,7 +293,8 @@ EnumVoicesRunnable::Run() {
}
RefPtr<RegisterVoicesRunnable> runnable = new RegisterVoicesRunnable(mSpeechService, list);
NS_DispatchToMainThread(runnable, NS_DISPATCH_SYNC);
NS_DispatchAndSpinEventLoopUntilComplete("EnumVoicesRunnable"_ns,
GetMainThreadSerialEventTarget(), runnable.forget());
return NS_OK;

View file

@ -13,6 +13,7 @@
#include "mozilla/webgpu/WebGPUParent.h"
#include "mozilla/webrender/RenderThread.h"
#include "nsIThread.h"
#include "nsThreadUtils.h"
namespace mozilla::gfx {
@ -60,11 +61,11 @@ CanvasManagerParent::ManagerSet CanvasManagerParent::sManagers;
return;
}
owningThread->Dispatch(
NS_NewRunnableFunction(
"CanvasManagerParent::Shutdown",
[]() -> void { CanvasManagerParent::ShutdownInternal(); }),
NS_DISPATCH_SYNC);
NS_DispatchAndSpinEventLoopUntilComplete(
"CanvasManagerParent::Shutdown"_ns, owningThread,
NS_NewRunnableFunction("CanvasManagerParent::Shutdown", []() -> void {
CanvasManagerParent::ShutdownInternal();
}));
}
/* static */ void CanvasManagerParent::ShutdownInternal() {

View file

@ -92,7 +92,8 @@ static int RunDecodeToSurfaceFuzzing(nsCOMPtr<nsIInputStream> inputStream,
RefPtr<SourceSurface> surface;
nsCOMPtr<nsIRunnable> runnable =
new DecodeToSurfaceRunnableFuzzing(surface, inputStream, mimeType);
thread->Dispatch(runnable, nsIThread::DISPATCH_SYNC);
NS_DispatchAndSpinEventLoopUntilComplete("RunDecodeToSurfaceFuzzing"_ns,
thread, runnable.forget());
thread->Shutdown();

View file

@ -95,7 +95,8 @@ static void RunDecodeToSurface(const ImageTestCase& aTestCase,
RefPtr<SourceSurface> surface;
nsCOMPtr<nsIRunnable> runnable = new DecodeToSurfaceRunnable(
surface, inputStream, aImageBuffer, aTestCase);
thread->Dispatch(runnable, nsIThread::DISPATCH_SYNC);
NS_DispatchAndSpinEventLoopUntilComplete("RunDecodeToSurface"_ns, thread,
do_AddRef(runnable));
thread->Shutdown();

View file

@ -720,9 +720,9 @@ bool MessageChannel::Open(MessageChannel* aTargetChan,
NodeController::GetSingleton()->CreatePortPair();
// NOTE: This dispatch must be sync as it captures locals by non-owning
// reference, however we can't use `NS_DISPATCH_SYNC` as that will spin a
// nested event loop, and doesn't work with certain types of calling event
// targets.
// reference, however we can't use `NS_DispatchAndSpinEventLoopUntilComplete`
// as that will spin a nested event loop, and doesn't work with certain types
// of calling event targets.
base::WaitableEvent event(/* manual_reset */ true,
/* initially_signaled */ false);
MOZ_ALWAYS_SUCCEEDS(aEventTarget->Dispatch(NS_NewCancelableRunnableFunction(

View file

@ -669,10 +669,11 @@ Result<Ok, nsresult> ScriptPreloader::WriteCache() {
if (!mDataPrepared && !mSaveComplete) {
MonitorSingleWriterAutoUnlock mau(mSaveMonitor);
NS_DispatchToMainThread(
NS_DispatchAndSpinEventLoopUntilComplete(
"ScriptPreloader::PrepareCacheWrite"_ns,
GetMainThreadSerialEventTarget(),
NewRunnableMethod("ScriptPreloader::PrepareCacheWrite", this,
&ScriptPreloader::PrepareCacheWrite),
NS_DISPATCH_SYNC);
&ScriptPreloader::PrepareCacheWrite));
}
if (mSaveComplete) {

View file

@ -134,9 +134,8 @@ class FakeAudioTrack : public ProcessedMediaTrack {
template <typename Function>
void RunOnSts(Function&& aFunction) {
MOZ_ALWAYS_SUCCEEDS(test_utils->sts_target()->Dispatch(
NS_NewRunnableFunction(__func__, [&] { aFunction(); }),
nsISerialEventTarget::DISPATCH_SYNC));
MOZ_ALWAYS_SUCCEEDS(test_utils->SyncDispatchToSTS(
NS_NewRunnableFunction(__func__, [&] { aFunction(); })));
}
class LoopbackTransport : public MediaTransportHandler {
@ -305,9 +304,7 @@ class TestAgent {
audio_track_ = nullptr;
}
test_utils->sts_target()->Dispatch(
WrapRunnable(this, &TestAgent::Shutdown_s),
nsISerialEventTarget::DISPATCH_SYNC);
test_utils->SyncDispatchToSTS(WrapRunnable(this, &TestAgent::Shutdown_s));
}
uint32_t GetRemoteSSRC() {
@ -460,9 +457,8 @@ class MediaPipelineTest : public ::testing::Test {
// Setup transport.
void InitTransports() {
test_utils->sts_target()->Dispatch(
WrapRunnableNM(&TestAgent::Connect, &p2_, &p1_),
nsISerialEventTarget::DISPATCH_SYNC);
test_utils->SyncDispatchToSTS(
WrapRunnableNM(&TestAgent::Connect, &p2_, &p1_));
}
// Verify RTP and RTCP

View file

@ -453,9 +453,12 @@ nsresult nsPACMan::DispatchToPAC(already_AddRefed<nsIRunnable> aEvent,
}
}
return mPACThread->Dispatch(
e.forget(),
aSync ? nsIEventTarget::DISPATCH_SYNC : nsIEventTarget::DISPATCH_NORMAL);
if (aSync) {
return NS_DispatchAndSpinEventLoopUntilComplete(
"nsPACMan::DispatchToPAC"_ns, mPACThread, e.forget());
} else {
return mPACThread->Dispatch(e.forget());
}
}
nsresult nsPACMan::AsyncGetProxyForURI(nsIURI* uri, nsPACManCallback* callback,

View file

@ -133,38 +133,35 @@ TEST(TestBind, MainTest)
auto* sts = gSocketTransportService;
ASSERT_TRUE(sts);
for (int32_t tried = 0; tried < 100; tried++) {
sts->Dispatch(
NS_NewRunnableFunction(
"test",
[&]() {
nsCOMPtr<nsISocketTransport> client;
rv = service->CreateTransport(nsTArray<nsCString>(),
"127.0.0.1"_ns, serverPort, nullptr,
nullptr, getter_AddRefs(client));
ASSERT_NS_SUCCEEDED(rv);
NS_DispatchAndSpinEventLoopUntilComplete(
"test"_ns, sts, NS_NewRunnableFunction("test", [&]() {
nsCOMPtr<nsISocketTransport> client;
rv = service->CreateTransport(nsTArray<nsCString>(), "127.0.0.1"_ns,
serverPort, nullptr, nullptr,
getter_AddRefs(client));
ASSERT_NS_SUCCEEDED(rv);
// Bind to a port. It's possible that we are binding to a port
// that is currently in use. If we failed to bind, we try next
// port.
NetAddr bindingAddr;
bindingAddr.inet.family = AF_INET;
bindingAddr.inet.ip = 0;
bindingAddr.inet.port = PR_htons(bindingPort);
rv = client->Bind(&bindingAddr);
ASSERT_NS_SUCCEEDED(rv);
// Bind to a port. It's possible that we are binding to a port
// that is currently in use. If we failed to bind, we try next
// port.
NetAddr bindingAddr;
bindingAddr.inet.family = AF_INET;
bindingAddr.inet.ip = 0;
bindingAddr.inet.port = PR_htons(bindingPort);
rv = client->Bind(&bindingAddr);
ASSERT_NS_SUCCEEDED(rv);
// Open IO streams, to make client SocketTransport connect to
// server.
clientCallback = new ClientInputCallback(waiter);
rv = client->OpenInputStream(nsITransport::OPEN_UNBUFFERED, 0, 0,
getter_AddRefs(inputStream));
ASSERT_NS_SUCCEEDED(rv);
// Open IO streams, to make client SocketTransport connect to
// server.
clientCallback = new ClientInputCallback(waiter);
rv = client->OpenInputStream(nsITransport::OPEN_UNBUFFERED, 0, 0,
getter_AddRefs(inputStream));
ASSERT_NS_SUCCEEDED(rv);
nsCOMPtr<nsIAsyncInputStream> asyncInputStream =
do_QueryInterface(inputStream);
rv = asyncInputStream->AsyncWait(clientCallback, 0, 0, nullptr);
}),
NS_DISPATCH_SYNC);
nsCOMPtr<nsIAsyncInputStream> asyncInputStream =
do_QueryInterface(inputStream);
rv = asyncInputStream->AsyncWait(clientCallback, 0, 0, nullptr);
}));
// Wait for server's response or callback of input stream.
waiter->Wait(1);

View file

@ -19,121 +19,117 @@ TEST(TestSocketTransportService, PortRemappingPreferenceReading)
auto* sts = gSocketTransportService;
ASSERT_TRUE(sts);
sts->Dispatch(
NS_NewRunnableFunction(
"test",
[&]() {
auto CheckPortRemap = [&](uint16_t input, uint16_t output) -> bool {
sts->ApplyPortRemap(&input);
return input == output;
};
NS_DispatchAndSpinEventLoopUntilComplete(
"test"_ns, sts, NS_NewRunnableFunction("test", [&]() {
auto CheckPortRemap = [&](uint16_t input, uint16_t output) -> bool {
sts->ApplyPortRemap(&input);
return input == output;
};
// Ill-formed prefs
ASSERT_FALSE(sts->UpdatePortRemapPreference(";"_ns));
ASSERT_FALSE(sts->UpdatePortRemapPreference(" ;"_ns));
ASSERT_FALSE(sts->UpdatePortRemapPreference("; "_ns));
ASSERT_FALSE(sts->UpdatePortRemapPreference("foo"_ns));
ASSERT_FALSE(sts->UpdatePortRemapPreference(" foo"_ns));
ASSERT_FALSE(sts->UpdatePortRemapPreference(" foo "_ns));
ASSERT_FALSE(sts->UpdatePortRemapPreference("10=20;"_ns));
// Ill-formed prefs
ASSERT_FALSE(sts->UpdatePortRemapPreference(";"_ns));
ASSERT_FALSE(sts->UpdatePortRemapPreference(" ;"_ns));
ASSERT_FALSE(sts->UpdatePortRemapPreference("; "_ns));
ASSERT_FALSE(sts->UpdatePortRemapPreference("foo"_ns));
ASSERT_FALSE(sts->UpdatePortRemapPreference(" foo"_ns));
ASSERT_FALSE(sts->UpdatePortRemapPreference(" foo "_ns));
ASSERT_FALSE(sts->UpdatePortRemapPreference("10=20;"_ns));
ASSERT_FALSE(sts->UpdatePortRemapPreference("1"_ns));
ASSERT_FALSE(sts->UpdatePortRemapPreference("1="_ns));
ASSERT_FALSE(sts->UpdatePortRemapPreference("1,="_ns));
ASSERT_FALSE(sts->UpdatePortRemapPreference("1-="_ns));
ASSERT_FALSE(sts->UpdatePortRemapPreference("1-,="_ns));
ASSERT_FALSE(sts->UpdatePortRemapPreference("1"_ns));
ASSERT_FALSE(sts->UpdatePortRemapPreference("1="_ns));
ASSERT_FALSE(sts->UpdatePortRemapPreference("1,="_ns));
ASSERT_FALSE(sts->UpdatePortRemapPreference("1-="_ns));
ASSERT_FALSE(sts->UpdatePortRemapPreference("1-,="_ns));
ASSERT_FALSE(sts->UpdatePortRemapPreference("1=2,"_ns));
ASSERT_FALSE(sts->UpdatePortRemapPreference("1=2-3"_ns));
ASSERT_FALSE(sts->UpdatePortRemapPreference("1-2,=3"_ns));
ASSERT_FALSE(sts->UpdatePortRemapPreference("1-2,3"_ns));
ASSERT_FALSE(sts->UpdatePortRemapPreference("1-2,3-4"_ns));
ASSERT_FALSE(sts->UpdatePortRemapPreference("1-2,3-4,"_ns));
ASSERT_FALSE(sts->UpdatePortRemapPreference("1-2,3-4="_ns));
ASSERT_FALSE(sts->UpdatePortRemapPreference("10000000=10"_ns));
ASSERT_FALSE(sts->UpdatePortRemapPreference("1=2,"_ns));
ASSERT_FALSE(sts->UpdatePortRemapPreference("1=2-3"_ns));
ASSERT_FALSE(sts->UpdatePortRemapPreference("1-2,=3"_ns));
ASSERT_FALSE(sts->UpdatePortRemapPreference("1-2,3"_ns));
ASSERT_FALSE(sts->UpdatePortRemapPreference("1-2,3-4"_ns));
ASSERT_FALSE(sts->UpdatePortRemapPreference("1-2,3-4,"_ns));
ASSERT_FALSE(sts->UpdatePortRemapPreference("1-2,3-4="_ns));
ASSERT_FALSE(sts->UpdatePortRemapPreference("10000000=10"_ns));
ASSERT_FALSE(sts->UpdatePortRemapPreference("1=2;3"_ns));
ASSERT_FALSE(sts->UpdatePortRemapPreference("1-4=2;3"_ns));
ASSERT_FALSE(sts->UpdatePortRemapPreference("1-4=2;3="_ns));
ASSERT_FALSE(sts->UpdatePortRemapPreference("1-foo=2;3=15"_ns));
ASSERT_FALSE(sts->UpdatePortRemapPreference("1-4=foo;3=15"_ns));
ASSERT_FALSE(sts->UpdatePortRemapPreference("1-4=2;foo=15"_ns));
ASSERT_FALSE(sts->UpdatePortRemapPreference("1-4=2;3=foo"_ns));
ASSERT_FALSE(sts->UpdatePortRemapPreference("1-4=2x3=15"_ns));
ASSERT_FALSE(sts->UpdatePortRemapPreference("1+4=2;3=15"_ns));
ASSERT_FALSE(sts->UpdatePortRemapPreference("1=2;3"_ns));
ASSERT_FALSE(sts->UpdatePortRemapPreference("1-4=2;3"_ns));
ASSERT_FALSE(sts->UpdatePortRemapPreference("1-4=2;3="_ns));
ASSERT_FALSE(sts->UpdatePortRemapPreference("1-foo=2;3=15"_ns));
ASSERT_FALSE(sts->UpdatePortRemapPreference("1-4=foo;3=15"_ns));
ASSERT_FALSE(sts->UpdatePortRemapPreference("1-4=2;foo=15"_ns));
ASSERT_FALSE(sts->UpdatePortRemapPreference("1-4=2;3=foo"_ns));
ASSERT_FALSE(sts->UpdatePortRemapPreference("1-4=2x3=15"_ns));
ASSERT_FALSE(sts->UpdatePortRemapPreference("1+4=2;3=15"_ns));
// Well-formed prefs
ASSERT_TRUE(sts->UpdatePortRemapPreference("1=2"_ns));
ASSERT_TRUE(CheckPortRemap(1, 2));
ASSERT_TRUE(CheckPortRemap(2, 2));
ASSERT_TRUE(CheckPortRemap(3, 3));
// Well-formed prefs
ASSERT_TRUE(sts->UpdatePortRemapPreference("1=2"_ns));
ASSERT_TRUE(CheckPortRemap(1, 2));
ASSERT_TRUE(CheckPortRemap(2, 2));
ASSERT_TRUE(CheckPortRemap(3, 3));
ASSERT_TRUE(sts->UpdatePortRemapPreference("10=20"_ns));
ASSERT_TRUE(CheckPortRemap(1, 1));
ASSERT_TRUE(CheckPortRemap(2, 2));
ASSERT_TRUE(CheckPortRemap(3, 3));
ASSERT_TRUE(CheckPortRemap(10, 20));
ASSERT_TRUE(sts->UpdatePortRemapPreference("10=20"_ns));
ASSERT_TRUE(CheckPortRemap(1, 1));
ASSERT_TRUE(CheckPortRemap(2, 2));
ASSERT_TRUE(CheckPortRemap(3, 3));
ASSERT_TRUE(CheckPortRemap(10, 20));
ASSERT_TRUE(sts->UpdatePortRemapPreference("100-200=1000"_ns));
ASSERT_TRUE(CheckPortRemap(10, 10));
ASSERT_TRUE(CheckPortRemap(99, 99));
ASSERT_TRUE(CheckPortRemap(100, 1000));
ASSERT_TRUE(CheckPortRemap(101, 1000));
ASSERT_TRUE(CheckPortRemap(200, 1000));
ASSERT_TRUE(CheckPortRemap(201, 201));
ASSERT_TRUE(sts->UpdatePortRemapPreference("100-200=1000"_ns));
ASSERT_TRUE(CheckPortRemap(10, 10));
ASSERT_TRUE(CheckPortRemap(99, 99));
ASSERT_TRUE(CheckPortRemap(100, 1000));
ASSERT_TRUE(CheckPortRemap(101, 1000));
ASSERT_TRUE(CheckPortRemap(200, 1000));
ASSERT_TRUE(CheckPortRemap(201, 201));
ASSERT_TRUE(sts->UpdatePortRemapPreference("100-200,500=1000"_ns));
ASSERT_TRUE(CheckPortRemap(10, 10));
ASSERT_TRUE(CheckPortRemap(99, 99));
ASSERT_TRUE(CheckPortRemap(100, 1000));
ASSERT_TRUE(CheckPortRemap(101, 1000));
ASSERT_TRUE(CheckPortRemap(200, 1000));
ASSERT_TRUE(CheckPortRemap(201, 201));
ASSERT_TRUE(CheckPortRemap(499, 499));
ASSERT_TRUE(CheckPortRemap(500, 1000));
ASSERT_TRUE(CheckPortRemap(501, 501));
ASSERT_TRUE(sts->UpdatePortRemapPreference("100-200,500=1000"_ns));
ASSERT_TRUE(CheckPortRemap(10, 10));
ASSERT_TRUE(CheckPortRemap(99, 99));
ASSERT_TRUE(CheckPortRemap(100, 1000));
ASSERT_TRUE(CheckPortRemap(101, 1000));
ASSERT_TRUE(CheckPortRemap(200, 1000));
ASSERT_TRUE(CheckPortRemap(201, 201));
ASSERT_TRUE(CheckPortRemap(499, 499));
ASSERT_TRUE(CheckPortRemap(500, 1000));
ASSERT_TRUE(CheckPortRemap(501, 501));
ASSERT_TRUE(sts->UpdatePortRemapPreference("1-3=10;5-8,12=20"_ns));
ASSERT_TRUE(CheckPortRemap(1, 10));
ASSERT_TRUE(CheckPortRemap(2, 10));
ASSERT_TRUE(CheckPortRemap(3, 10));
ASSERT_TRUE(CheckPortRemap(4, 4));
ASSERT_TRUE(CheckPortRemap(5, 20));
ASSERT_TRUE(CheckPortRemap(8, 20));
ASSERT_TRUE(CheckPortRemap(11, 11));
ASSERT_TRUE(CheckPortRemap(12, 20));
ASSERT_TRUE(sts->UpdatePortRemapPreference("1-3=10;5-8,12=20"_ns));
ASSERT_TRUE(CheckPortRemap(1, 10));
ASSERT_TRUE(CheckPortRemap(2, 10));
ASSERT_TRUE(CheckPortRemap(3, 10));
ASSERT_TRUE(CheckPortRemap(4, 4));
ASSERT_TRUE(CheckPortRemap(5, 20));
ASSERT_TRUE(CheckPortRemap(8, 20));
ASSERT_TRUE(CheckPortRemap(11, 11));
ASSERT_TRUE(CheckPortRemap(12, 20));
ASSERT_TRUE(sts->UpdatePortRemapPreference("80=8080;443=8080"_ns));
ASSERT_TRUE(CheckPortRemap(80, 8080));
ASSERT_TRUE(CheckPortRemap(443, 8080));
ASSERT_TRUE(sts->UpdatePortRemapPreference("80=8080;443=8080"_ns));
ASSERT_TRUE(CheckPortRemap(80, 8080));
ASSERT_TRUE(CheckPortRemap(443, 8080));
// Later rules rewrite earlier rules
ASSERT_TRUE(sts->UpdatePortRemapPreference("10=100;10=200"_ns));
ASSERT_TRUE(CheckPortRemap(10, 200));
// Later rules rewrite earlier rules
ASSERT_TRUE(sts->UpdatePortRemapPreference("10=100;10=200"_ns));
ASSERT_TRUE(CheckPortRemap(10, 200));
ASSERT_TRUE(
sts->UpdatePortRemapPreference("10-20=100;10-20=200"_ns));
ASSERT_TRUE(CheckPortRemap(10, 200));
ASSERT_TRUE(CheckPortRemap(20, 200));
ASSERT_TRUE(sts->UpdatePortRemapPreference("10-20=100;10-20=200"_ns));
ASSERT_TRUE(CheckPortRemap(10, 200));
ASSERT_TRUE(CheckPortRemap(20, 200));
ASSERT_TRUE(sts->UpdatePortRemapPreference("10-20=100;15=200"_ns));
ASSERT_TRUE(CheckPortRemap(10, 100));
ASSERT_TRUE(CheckPortRemap(15, 200));
ASSERT_TRUE(CheckPortRemap(20, 100));
ASSERT_TRUE(sts->UpdatePortRemapPreference("10-20=100;15=200"_ns));
ASSERT_TRUE(CheckPortRemap(10, 100));
ASSERT_TRUE(CheckPortRemap(15, 200));
ASSERT_TRUE(CheckPortRemap(20, 100));
ASSERT_TRUE(sts->UpdatePortRemapPreference(
" 100 - 200 = 1000 ; 150 = 2000 "_ns));
ASSERT_TRUE(CheckPortRemap(100, 1000));
ASSERT_TRUE(CheckPortRemap(150, 2000));
ASSERT_TRUE(CheckPortRemap(200, 1000));
ASSERT_TRUE(sts->UpdatePortRemapPreference(
" 100 - 200 = 1000 ; 150 = 2000 "_ns));
ASSERT_TRUE(CheckPortRemap(100, 1000));
ASSERT_TRUE(CheckPortRemap(150, 2000));
ASSERT_TRUE(CheckPortRemap(200, 1000));
// Turn off any mapping
ASSERT_TRUE(sts->UpdatePortRemapPreference(""_ns));
for (uint32_t port = 0; port < 65536; ++port) {
ASSERT_TRUE(CheckPortRemap((uint16_t)port, (uint16_t)port));
}
}),
NS_DISPATCH_SYNC);
// Turn off any mapping
ASSERT_TRUE(sts->UpdatePortRemapPreference(""_ns));
for (uint32_t port = 0; port < 65536; ++port) {
ASSERT_TRUE(CheckPortRemap((uint16_t)port, (uint16_t)port));
}
}));
}
} // namespace net

View file

@ -186,7 +186,8 @@ NS_IMETHODIMP nsWifiMonitor::Run() {
new nsPassErrorToWifiListeners(std::move(currentListeners), rv));
if (!runnable) return NS_ERROR_OUT_OF_MEMORY;
target->Dispatch(runnable, NS_DISPATCH_SYNC);
NS_DispatchAndSpinEventLoopUntilComplete("nsWifiMonitor::Run"_ns, target,
runnable.forget());
}
LOG(("@@@@@ wifi monitor run complete\n"));
@ -251,7 +252,8 @@ nsresult nsWifiMonitor::CallWifiListeners(
std::move(currentListeners), std::move(accessPoints)));
if (!runnable) return NS_ERROR_OUT_OF_MEMORY;
thread->Dispatch(runnable, NS_DISPATCH_SYNC);
NS_DispatchAndSpinEventLoopUntilComplete(
"nsWifiMonitor::CallWifiListeners"_ns, thread, runnable.forget());
}
return NS_OK;

View file

@ -15,7 +15,8 @@ namespace psm {
// Wait for the event to run on the target thread without spinning the event
// loop on the calling thread. (Dispatching events to a thread using
// NS_DISPATCH_SYNC would cause the event loop on the calling thread to spin.)
// NS_DispatchAndSpinEventLoopUntilComplete would cause the event loop on the
// calling thread to spin.)
class SyncRunnableBase : public Runnable {
public:
NS_DECL_NSIRUNNABLE

View file

@ -96,11 +96,12 @@ void ChildProfilerController::ShutdownAndMaybeGrabShutdownProfileFirst(
// If we're not profiling, this operation will be very quick, so it can be
// done synchronously. This avoids having to manually shutdown the thread,
// which runs a risky inner event loop, see bug 1613798.
profilerChildThread->Dispatch(
NS_DispatchAndSpinEventLoopUntilComplete(
"ChildProfilerController::ShutdownProfilerChild SYNC"_ns,
profilerChildThread,
NewRunnableMethod<ProfileAndAdditionalInformation*>(
"ChildProfilerController::ShutdownProfilerChild SYNC", this,
&ChildProfilerController::ShutdownProfilerChild, nullptr),
NS_DISPATCH_SYNC);
&ChildProfilerController::ShutdownProfilerChild, nullptr));
}
// At this point, `profilerChildThread` should be the last reference to the
// thread, so it will now get destroyed.

View file

@ -1917,15 +1917,14 @@ TEST(GeckoProfiler, DifferentThreads)
uint32_t features = ProfilerFeature::JS;
const char* filters[] = {"GeckoMain", "Compositor"};
thread->Dispatch(
NS_NewRunnableFunction("GeckoProfiler_DifferentThreads_Test::TestBody",
[&]() {
profiler_start(PROFILER_DEFAULT_ENTRIES,
PROFILER_DEFAULT_INTERVAL,
features, filters,
MOZ_ARRAY_LENGTH(filters), 0);
}),
NS_DISPATCH_SYNC);
NS_DispatchAndSpinEventLoopUntilComplete(
"GeckoProfiler_DifferentThreads_Test::TestBody"_ns, thread,
NS_NewRunnableFunction(
"GeckoProfiler_DifferentThreads_Test::TestBody", [&]() {
profiler_start(PROFILER_DEFAULT_ENTRIES,
PROFILER_DEFAULT_INTERVAL, features, filters,
MOZ_ARRAY_LENGTH(filters), 0);
}));
ASSERT_TRUE(profiler_is_active());
ASSERT_TRUE(!profiler_feature_active(ProfilerFeature::MainThreadIO));
@ -1935,10 +1934,10 @@ TEST(GeckoProfiler, DifferentThreads)
PROFILER_DEFAULT_INTERVAL, features, filters,
MOZ_ARRAY_LENGTH(filters), 0);
thread->Dispatch(
NS_DispatchAndSpinEventLoopUntilComplete(
"GeckoProfiler_DifferentThreads_Test::TestBody"_ns, thread,
NS_NewRunnableFunction("GeckoProfiler_DifferentThreads_Test::TestBody",
[&]() { profiler_stop(); }),
NS_DISPATCH_SYNC);
[&]() { profiler_stop(); }));
InactiveFeaturesAndParamsCheck();
}
@ -1952,10 +1951,10 @@ TEST(GeckoProfiler, DifferentThreads)
profiler_start(PROFILER_DEFAULT_ENTRIES, PROFILER_DEFAULT_INTERVAL,
features, filters, MOZ_ARRAY_LENGTH(filters), 0);
thread->Dispatch(
NS_DispatchAndSpinEventLoopUntilComplete(
"GeckoProfiler_DifferentThreads_Test::TestBody"_ns, thread,
NS_NewRunnableFunction(
"GeckoProfiler_DifferentThreads_Test::TestBody",
[&]() {
"GeckoProfiler_DifferentThreads_Test::TestBody", [&]() {
ASSERT_TRUE(profiler_is_active());
ASSERT_TRUE(
!profiler_feature_active(ProfilerFeature::MainThreadIO));
@ -1965,15 +1964,14 @@ TEST(GeckoProfiler, DifferentThreads)
ActiveParamsCheck(PROFILER_DEFAULT_ENTRIES.Value(),
PROFILER_DEFAULT_INTERVAL, features, filters,
MOZ_ARRAY_LENGTH(filters), 0);
}),
NS_DISPATCH_SYNC);
}));
profiler_stop();
thread->Dispatch(
NS_DispatchAndSpinEventLoopUntilComplete(
"GeckoProfiler_DifferentThreads_Test::TestBody"_ns, thread,
NS_NewRunnableFunction("GeckoProfiler_DifferentThreads_Test::TestBody",
[&]() { InactiveFeaturesAndParamsCheck(); }),
NS_DISPATCH_SYNC);
[&]() { InactiveFeaturesAndParamsCheck(); }));
}
thread->Shutdown();
@ -3867,7 +3865,9 @@ TEST(GeckoProfiler, StreamJSONForThisProcessThreaded)
filters, MOZ_ARRAY_LENGTH(filters), 0);
// Call profiler_stream_json_for_this_process on a background thread.
thread->Dispatch(
NS_DispatchAndSpinEventLoopUntilComplete(
"GeckoProfiler_StreamJSONForThisProcessThreaded_Test::TestBody"_ns,
thread,
NS_NewRunnableFunction(
"GeckoProfiler_StreamJSONForThisProcessThreaded_Test::TestBody",
[&]() {
@ -3879,8 +3879,7 @@ TEST(GeckoProfiler, StreamJSONForThisProcessThreaded)
mozilla::ProgressLogger{})
.isOk());
w.End();
}),
NS_DISPATCH_SYNC);
}));
MOZ_RELEASE_ASSERT(!w.ChunkedWriteFunc().Failed());
MOZ_RELEASE_ASSERT(!w.ChunkedWriteFunc().GetFailure());
@ -3893,7 +3892,9 @@ TEST(GeckoProfiler, StreamJSONForThisProcessThreaded)
// Stop the profiler and call profiler_stream_json_for_this_process on a
// background thread.
thread->Dispatch(
NS_DispatchAndSpinEventLoopUntilComplete(
"GeckoProfiler_StreamJSONForThisProcessThreaded_Test::TestBody"_ns,
thread,
NS_NewRunnableFunction(
"GeckoProfiler_StreamJSONForThisProcessThreaded_Test::TestBody",
[&]() {
@ -3904,8 +3905,7 @@ TEST(GeckoProfiler, StreamJSONForThisProcessThreaded)
/* ProfilerCodeAddressService* aService */ nullptr,
mozilla::ProgressLogger{})
.isErr());
}),
NS_DISPATCH_SYNC);
}));
thread->Shutdown();
// Call profiler_stream_json_for_this_process on the main thread.
@ -3982,10 +3982,10 @@ class GTestStackCollector final : public ProfilerStackCollector {
void DoSuspendAndSample(ProfilerThreadId aTidToSample,
nsIThread* aSamplingThread) {
aSamplingThread->Dispatch(
NS_DispatchAndSpinEventLoopUntilComplete(
"GeckoProfiler_SuspendAndSample_Test::TestBody"_ns, aSamplingThread,
NS_NewRunnableFunction(
"GeckoProfiler_SuspendAndSample_Test::TestBody",
[&]() {
"GeckoProfiler_SuspendAndSample_Test::TestBody", [&]() {
uint32_t features = ProfilerFeature::CPUUtilization;
GTestStackCollector collector;
profiler_suspend_and_sample_thread(aTidToSample, features,
@ -3995,8 +3995,7 @@ void DoSuspendAndSample(ProfilerThreadId aTidToSample,
ASSERT_TRUE(collector.mSetIsMainThread ==
(aTidToSample == profiler_main_thread_id()));
ASSERT_TRUE(collector.mFrames > 0);
}),
NS_DISPATCH_SYNC);
}));
}
TEST(GeckoProfiler, SuspendAndSample)

View file

@ -74,12 +74,8 @@ class AndroidUiThread : public nsThread {
NS_IMETHODIMP
AndroidUiThread::Dispatch(already_AddRefed<nsIRunnable> aEvent,
uint32_t aFlags) {
if (aFlags & NS_DISPATCH_SYNC) {
return nsThread::Dispatch(std::move(aEvent), aFlags);
} else {
EnqueueTask(std::move(aEvent), 0);
return NS_OK;
}
EnqueueTask(std::move(aEvent), 0);
return NS_OK;
}
NS_IMETHODIMP

View file

@ -74,7 +74,9 @@ HWND GetHiddenWindowHWND() {
// Need to dispatch this to the main thread because plenty of
// the things it wants to access are main-thread-only.
RefPtr<HWNDGetter> getter = new HWNDGetter();
NS_DispatchToMainThread(getter, NS_DISPATCH_SYNC);
NS_DispatchAndSpinEventLoopUntilComplete(
"GetHiddenWindowHWND"_ns, mozilla::GetMainThreadSerialEventTarget(),
do_AddRef(getter));
return getter->hidden_window_hwnd;
}

View file

@ -135,8 +135,6 @@ pub unsafe fn dispatch_background_task_runnable(
}
/// Options to control how task runnables are dispatched.
///
/// NOTE: The `DISPATCH_SYNC` flag is intentionally not supported by this type.
#[derive(Copy, Clone, Debug, Eq, Hash, PartialEq)]
pub struct DispatchOptions(u32);

View file

@ -65,7 +65,8 @@ TEST(ThreadPool, Parallelism)
// Dispatch and sleep to ensure we have an idle thread
nsCOMPtr<nsIRunnable> r0 = new Runnable("TestRunnable");
pool->Dispatch(r0, NS_DISPATCH_SYNC);
NS_DispatchAndSpinEventLoopUntilComplete("ThreadPool::Parallelism"_ns, pool,
do_AddRef(r0));
PR_Sleep(PR_SecondsToInterval(2));
class Runnable1 : public Runnable {

View file

@ -163,12 +163,12 @@ class TimerHelper {
}
void Cancel() {
mTarget->Dispatch(NS_NewRunnableFunction("~TimerHelper timer cancel",
[this] {
MonitorAutoLock lock(mMonitor);
mTimer->Cancel();
}),
NS_DISPATCH_SYNC);
NS_DispatchAndSpinEventLoopUntilComplete(
"~TimerHelper timer cancel"_ns, mTarget,
NS_NewRunnableFunction("~TimerHelper timer cancel", [this] {
MonitorAutoLock lock(mMonitor);
mTimer->Cancel();
}));
}
private:

View file

@ -18,11 +18,11 @@ namespace mozilla {
/**
* This class will wrap a nsIRunnable and dispatch it to the target thread
* synchronously. This is different from nsIEventTarget.DISPATCH_SYNC:
* this class does not spin the event loop waiting for the event to be
* dispatched. This means that you don't risk reentrance from pending
* messages, but you must be sure that the target thread does not ever block
* on this thread, or else you will deadlock.
* synchronously. This is different from
* NS_DispatchAndSpinEventLoopUntilComplete: this class does not spin the event
* loop waiting for the event to be dispatched. This means that you don't risk
* reentrance from pending messages, but you must be sure that the target thread
* does not ever block on this thread, or else you will deadlock.
*
* Typical usage:
* RefPtr<SyncRunnable> sr = new SyncRunnable(new myrunnable...());

View file

@ -86,40 +86,6 @@ ThreadEventTarget::Dispatch(already_AddRefed<nsIRunnable> aEvent,
LogRunnable::LogDispatch(event.get());
if (aFlags & DISPATCH_SYNC) {
// NOTE: Get the current thread specifically, as `SpinEventLoopUntil` can
// only spin that event target's loop. The reply will specify
// NS_DISPATCH_IGNORE_BLOCK_DISPATCH to ensure the reply is received even if
// the caller is a threadpool thread.
nsCOMPtr<nsIThread> current = NS_GetCurrentThread();
if (NS_WARN_IF(!current)) {
return NS_ERROR_NOT_AVAILABLE;
}
// XXX we should be able to do something better here... we should
// be able to monitor the slot occupied by this event and use
// that to tell us when the event has been processed.
RefPtr<nsThreadSyncDispatch> wrapper =
new nsThreadSyncDispatch(current.forget(), event.take());
bool success = mSink->PutEvent(do_AddRef(wrapper),
EventQueuePriority::Normal); // hold a ref
if (!success) {
// 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 NS_ERROR_UNEXPECTED;
}
// Allows waiting; ensure no locks are held that would deadlock us!
SpinEventLoopUntil(
"ThreadEventTarget::Dispatch"_ns,
[&, wrapper]() -> bool { return !wrapper->IsPending(); });
return NS_OK;
}
NS_ASSERTION((aFlags & (NS_DISPATCH_AT_END |
NS_DISPATCH_IGNORE_BLOCK_DISPATCH)) == aFlags,
"unexpected dispatch flags");

View file

@ -34,15 +34,7 @@ interface nsIEventTarget : nsISupports
*/
const unsigned long DISPATCH_NORMAL = 0;
/**
* This flag specifies the synchronous mode of event dispatch, in which the
* dispatch method does not return until the event has been processed.
*
* NOTE: passing this flag to dispatch may have the side-effect of causing
* other events on the current thread to be processed while waiting for the
* given event to be processed.
*/
const unsigned long DISPATCH_SYNC = 1;
// NOTE: 1 used to be DISPATCH_SYNC
/**
* This flag specifies that the dispatch is occurring from a running event
@ -222,7 +214,6 @@ public:
%{C++
// convenient aliases:
#define NS_DISPATCH_NORMAL nsIEventTarget::DISPATCH_NORMAL
#define NS_DISPATCH_SYNC nsIEventTarget::DISPATCH_SYNC
#define NS_DISPATCH_AT_END nsIEventTarget::DISPATCH_AT_END
#define NS_DISPATCH_EVENT_MAY_BLOCK nsIEventTarget::DISPATCH_EVENT_MAY_BLOCK
#define NS_DISPATCH_IGNORE_BLOCK_DISPATCH nsIEventTarget::DISPATCH_IGNORE_BLOCK_DISPATCH

View file

@ -375,25 +375,9 @@ nsThreadPool::Dispatch(already_AddRefed<nsIRunnable> aEvent, uint32_t aFlags) {
return NS_ERROR_NOT_AVAILABLE;
}
if (aFlags & DISPATCH_SYNC) {
nsCOMPtr<nsIThread> thread;
nsThreadManager::get().GetCurrentThread(getter_AddRefs(thread));
if (NS_WARN_IF(!thread)) {
return NS_ERROR_NOT_AVAILABLE;
}
RefPtr<nsThreadSyncDispatch> wrapper =
new nsThreadSyncDispatch(thread.forget(), std::move(aEvent));
PutEvent(wrapper);
SpinEventLoopUntil("nsThreadPool::Dispatch"_ns, [&, wrapper]() -> bool {
return !wrapper->IsPending();
});
} else {
NS_ASSERTION(aFlags == NS_DISPATCH_NORMAL || aFlags == NS_DISPATCH_AT_END,
"unexpected dispatch flags");
PutEvent(std::move(aEvent), aFlags);
}
NS_ASSERTION(aFlags == NS_DISPATCH_NORMAL || aFlags == NS_DISPATCH_AT_END,
"unexpected dispatch flags");
PutEvent(std::move(aEvent), aFlags);
return NS_OK;
}

View file

@ -9,6 +9,7 @@
#include "mozilla/Atomics.h"
#include "mozilla/DebugOnly.h"
#include "mozilla/SpinEventLoopUntil.h"
#include "nsThreadUtils.h"
#include "LeakRefPtr.h"
@ -27,6 +28,11 @@ class nsThreadSyncDispatch : public mozilla::Runnable {
return mIsPending;
}
void SpinEventLoopUntilComplete(const nsACString& aVeryGoodReasonToDoThis) {
mozilla::SpinEventLoopUntil(aVeryGoodReasonToDoThis,
[&]() -> bool { return !IsPending(); });
}
private:
NS_IMETHOD Run() override {
if (nsCOMPtr<nsIRunnable> task = mSyncTask.take()) {

View file

@ -15,6 +15,8 @@
#include "nsExceptionHandler.h"
#include "nsIEventTarget.h"
#include "nsITimer.h"
#include "nsString.h"
#include "nsThreadSyncDispatch.h"
#include "nsTimerImpl.h"
#include "prsystem.h"
@ -739,3 +741,28 @@ nsresult NS_CreateBackgroundTaskQueue(const char* aName,
}
} // extern "C"
nsresult NS_DispatchAndSpinEventLoopUntilComplete(
const nsACString& aVeryGoodReasonToDoThis, nsIEventTarget* aEventTarget,
already_AddRefed<nsIRunnable> aEvent) {
// NOTE: Get the current thread specifically, as `SpinEventLoopUntil` can
// only spin that event target's loop. The reply will specify
// NS_DISPATCH_IGNORE_BLOCK_DISPATCH to ensure the reply is received even if
// the caller is a threadpool thread.
nsCOMPtr<nsIThread> current = NS_GetCurrentThread();
if (NS_WARN_IF(!current)) {
return NS_ERROR_NOT_AVAILABLE;
}
RefPtr<nsThreadSyncDispatch> wrapper =
new nsThreadSyncDispatch(current.forget(), std::move(aEvent));
nsresult rv = aEventTarget->Dispatch(do_AddRef(wrapper));
if (NS_WARN_IF(NS_FAILED(rv))) {
// FIXME: Consider avoiding leaking the `nsThreadSyncDispatch` as well by
// using a fallible version of `Dispatch` once that is added.
return rv;
}
wrapper->SpinEventLoopUntilComplete(aVeryGoodReasonToDoThis);
return NS_OK;
}

View file

@ -1755,6 +1755,17 @@ extern "C" nsresult NS_DispatchBackgroundTask(
extern "C" nsresult NS_CreateBackgroundTaskQueue(
const char* aName, nsISerialEventTarget** aTarget);
/**
* Dispatch the given runnable to the given event target, spinning the current
* thread's event loop until the runnable has finished executing.
*
* This is roughly equivalent to the previously-supported `NS_DISPATCH_SYNC`
* flag.
*/
extern nsresult NS_DispatchAndSpinEventLoopUntilComplete(
const nsACString& aVeryGoodReasonToDoThis, nsIEventTarget* aEventTarget,
already_AddRefed<nsIRunnable> aEvent);
// Predeclaration for logging function below
namespace IPC {
class Message;