1 /* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
3 * You can obtain one at http://mozilla.org/MPL/2.0/. */
5 #include "BackgroundChild.h"
6 #include "BackgroundParent.h"
8 #include "BackgroundChildImpl.h"
9 #include "BackgroundParentImpl.h"
10 #include "base/process_util.h"
11 #include "FileDescriptor.h"
12 #include "GeckoProfiler.h"
13 #include "InputStreamUtils.h"
14 #include "mozilla/Assertions.h"
15 #include "mozilla/Atomics.h"
16 #include "mozilla/ClearOnShutdown.h"
17 #include "mozilla/DebugOnly.h"
18 #include "mozilla/Services.h"
19 #include "mozilla/StaticPtr.h"
20 #include "mozilla/unused.h"
21 #include "mozilla/dom/ContentChild.h"
22 #include "mozilla/dom/ContentParent.h"
23 #include "mozilla/dom/File.h"
24 #include "mozilla/dom/ipc/BlobChild.h"
25 #include "mozilla/dom/ipc/BlobParent.h"
26 #include "mozilla/dom/ipc/nsIRemoteBlob.h"
27 #include "mozilla/ipc/ProtocolTypes.h"
28 #include "nsAutoPtr.h"
30 #include "nsIEventTarget.h"
31 #include "nsIIPCBackgroundChildCreateCallback.h"
32 #include "nsIMutable.h"
33 #include "nsIObserver.h"
34 #include "nsIObserverService.h"
35 #include "nsIRunnable.h"
36 #include "nsISupportsImpl.h"
37 #include "nsIThread.h"
40 #include "nsThreadUtils.h"
41 #include "nsTraceRefcnt.h"
42 #include "nsXULAppAPI.h"
43 #include "nsXPCOMPrivate.h"
47 #define THREADSAFETY_ASSERT MOZ_ASSERT
49 #define THREADSAFETY_ASSERT MOZ_RELEASE_ASSERT
52 #define CRASH_IN_CHILD_PROCESS(_msg) \
54 if (IsMainProcess()) { \
55 MOZ_ASSERT(false, _msg); \
62 using namespace mozilla
;
63 using namespace mozilla::dom
;
64 using namespace mozilla::ipc
;
68 // -----------------------------------------------------------------------------
70 // -----------------------------------------------------------------------------
75 static const bool isMainProcess
=
76 XRE_GetProcessType() == GeckoProcessType_Default
;
84 return !IsMainProcess();
89 AssertIsInMainProcess()
91 MOZ_ASSERT(IsMainProcess());
95 AssertIsInChildProcess()
97 MOZ_ASSERT(IsChildProcess());
101 AssertIsOnMainThread()
103 THREADSAFETY_ASSERT(NS_IsMainThread());
106 // -----------------------------------------------------------------------------
107 // ParentImpl Declaration
108 // -----------------------------------------------------------------------------
110 class ParentImpl MOZ_FINAL
: public BackgroundParentImpl
112 friend class mozilla::ipc::BackgroundParent
;
115 class CreateCallback
;
118 class ShutdownObserver
;
119 class RequestMessageLoopRunnable
;
120 class ShutdownBackgroundThreadRunnable
;
121 class ForceCloseBackgroundActorsRunnable
;
122 class CreateCallbackRunnable
;
123 class ConnectActorRunnable
;
125 struct MOZ_STACK_CLASS TimerCallbackClosure
128 nsTArray
<ParentImpl
*>* mLiveActors
;
130 TimerCallbackClosure(nsIThread
* aThread
, nsTArray
<ParentImpl
*>* aLiveActors
)
131 : mThread(aThread
), mLiveActors(aLiveActors
)
133 AssertIsInMainProcess();
134 AssertIsOnMainThread();
136 MOZ_ASSERT(aLiveActors
);
140 // A handle that is invalid on any platform.
141 static const ProcessHandle kInvalidProcessHandle
;
143 // The length of time we will wait at shutdown for all actors to clean
144 // themselves up before forcing them to be destroyed.
145 static const uint32_t kShutdownTimerDelayMS
= 10000;
147 // This is only modified on the main thread. It is null if the thread does not
148 // exist or is shutting down.
149 static StaticRefPtr
<nsIThread
> sBackgroundThread
;
151 // This is created and destroyed on the main thread but only modified on the
152 // background thread. It is specific to each instance of sBackgroundThread.
153 static nsTArray
<ParentImpl
*>* sLiveActorsForBackgroundThread
;
155 // This is only modified on the main thread.
156 static StaticRefPtr
<nsITimer
> sShutdownTimer
;
158 // This exists so that that [Assert]IsOnBackgroundThread() can continue to
159 // work during shutdown.
160 static Atomic
<PRThread
*> sBackgroundPRThread
;
162 // This is only modified on the main thread. It is null if the thread does not
163 // exist or is shutting down.
164 static MessageLoop
* sBackgroundThreadMessageLoop
;
166 // This is only modified on the main thread. It maintains a count of live
167 // actors so that the background thread can be shut down when it is no longer
169 static uint64_t sLiveActorCount
;
171 // This is only modified on the main thread. It is true after the shutdown
172 // observer is registered and is never unset thereafter.
173 static bool sShutdownObserverRegistered
;
175 // This is only modified on the main thread. It prevents us from trying to
176 // create the background thread after application shutdown has started.
177 static bool sShutdownHasStarted
;
179 // This is only modified on the main thread. It is a FIFO queue for callbacks
180 // waiting for the background thread to be created.
181 static StaticAutoPtr
<nsTArray
<nsRefPtr
<CreateCallback
>>> sPendingCallbacks
;
183 // Only touched on the main thread, null if this is a same-process actor.
184 nsRefPtr
<ContentParent
> mContent
;
186 // mTransport is "owned" by this object but it must only be released on the
187 // IPC thread. It's left as a raw pointer here to prevent accidentally
188 // deleting it on the wrong thread. Only non-null for other-process actors.
189 Transport
* mTransport
;
191 // Set when the actor is opened successfully and used to handle shutdown
192 // hangs. Only touched on the background thread.
193 nsTArray
<ParentImpl
*>* mLiveActorArray
;
195 // Set at construction to indicate whether this parent actor corresponds to a
196 // child actor in another process or to a child actor from a different thread
197 // in the same process.
198 const bool mIsOtherProcessActor
;
200 // Set after ActorDestroy has been called. Only touched on the background
202 bool mActorDestroyed
;
206 CreateActorForSameProcess(CreateCallback
* aCallback
);
209 IsOnBackgroundThread()
211 return PR_GetCurrentThread() == sBackgroundPRThread
;
215 AssertIsOnBackgroundThread()
217 THREADSAFETY_ASSERT(IsOnBackgroundThread());
220 NS_INLINE_DECL_REFCOUNTING(ParentImpl
)
226 // Forwarded from BackgroundParent.
228 IsOtherProcessActor(PBackgroundParent
* aBackgroundActor
);
230 // Forwarded from BackgroundParent.
231 static already_AddRefed
<ContentParent
>
232 GetContentParent(PBackgroundParent
* aBackgroundActor
);
234 // Forwarded from BackgroundParent.
236 GetRawContentParentForComparison(PBackgroundParent
* aBackgroundActor
);
238 // Forwarded from BackgroundParent.
239 static PBackgroundParent
*
240 Alloc(ContentParent
* aContent
,
241 Transport
* aTransport
,
242 ProcessId aOtherProcess
);
245 CreateBackgroundThread();
248 ShutdownBackgroundThread();
251 ShutdownTimerCallback(nsITimer
* aTimer
, void* aClosure
);
253 // For same-process actors.
255 : mTransport(nullptr), mLiveActorArray(nullptr), mIsOtherProcessActor(false),
256 mActorDestroyed(false)
258 AssertIsInMainProcess();
259 AssertIsOnMainThread();
261 SetOtherProcess(kInvalidProcessHandle
);
264 // For other-process actors.
265 ParentImpl(ContentParent
* aContent
, Transport
* aTransport
)
266 : mContent(aContent
), mTransport(aTransport
), mLiveActorArray(nullptr),
267 mIsOtherProcessActor(true), mActorDestroyed(false)
269 AssertIsInMainProcess();
270 AssertIsOnMainThread();
271 MOZ_ASSERT(aContent
);
272 MOZ_ASSERT(aTransport
);
277 AssertIsInMainProcess();
278 AssertIsOnMainThread();
279 MOZ_ASSERT(!mContent
);
280 MOZ_ASSERT(!mTransport
);
284 MainThreadActorDestroy();
287 SetLiveActorArray(nsTArray
<ParentImpl
*>* aLiveActorArray
)
289 AssertIsInMainProcess();
290 AssertIsOnBackgroundThread();
291 MOZ_ASSERT(aLiveActorArray
);
292 MOZ_ASSERT(!aLiveActorArray
->Contains(this));
293 MOZ_ASSERT(!mLiveActorArray
);
294 MOZ_ASSERT(mIsOtherProcessActor
);
296 mLiveActorArray
= aLiveActorArray
;
297 mLiveActorArray
->AppendElement(this);
300 // These methods are only called by IPDL.
301 virtual IToplevelProtocol
*
302 CloneToplevel(const InfallibleTArray
<ProtocolFdMapping
>& aFds
,
303 ProcessHandle aPeerProcess
,
304 ProtocolCloneContext
* aCtx
) MOZ_OVERRIDE
;
307 ActorDestroy(ActorDestroyReason aWhy
) MOZ_OVERRIDE
;
310 // -----------------------------------------------------------------------------
311 // ChildImpl Declaration
312 // -----------------------------------------------------------------------------
314 class ChildImpl MOZ_FINAL
: public BackgroundChildImpl
316 friend class mozilla::ipc::BackgroundChild
;
317 friend class mozilla::ipc::BackgroundChildImpl
;
319 typedef base::ProcessId ProcessId
;
320 typedef mozilla::ipc::Transport Transport
;
322 class ShutdownObserver
;
323 class CreateActorRunnable
;
324 class ParentCreateCallback
;
325 class AlreadyCreatedCallbackRunnable
;
326 class FailedCreateCallbackRunnable
;
327 class OpenChildProcessActorRunnable
;
328 class OpenMainProcessActorRunnable
;
330 // A thread-local index that is not valid.
331 static const unsigned int kBadThreadLocalIndex
=
332 static_cast<unsigned int>(-1);
334 // This is only modified on the main thread. It is the thread-local index that
335 // we use to store the BackgroundChild for each thread.
336 static unsigned int sThreadLocalIndex
;
338 struct ThreadLocalInfo
340 explicit ThreadLocalInfo(nsIIPCBackgroundChildCreateCallback
* aCallback
)
343 mCallbacks
.AppendElement(aCallback
);
346 nsRefPtr
<ChildImpl
> mActor
;
347 nsTArray
<nsCOMPtr
<nsIIPCBackgroundChildCreateCallback
>> mCallbacks
;
348 nsAutoPtr
<BackgroundChildImpl::ThreadLocal
> mConsumerThreadLocal
;
349 DebugOnly
<bool> mClosed
;
352 // This is only modified on the main thread. It is a FIFO queue for actors
353 // that are in the process of construction.
354 static StaticAutoPtr
<nsTArray
<nsCOMPtr
<nsIEventTarget
>>> sPendingTargets
;
356 // This is only modified on the main thread. It prevents us from trying to
357 // create the background thread after application shutdown has started.
358 static bool sShutdownHasStarted
;
361 DebugOnly
<nsIThread
*> mBoundThread
;
363 nsIThread
* mBoundThread
;
366 DebugOnly
<bool> mActorDestroyed
;
370 OpenProtocolOnMainThread(nsIEventTarget
* aEventTarget
);
376 AssertIsOnBoundThread()
378 THREADSAFETY_ASSERT(mBoundThread
);
381 DebugOnly
<bool> current
;
386 NS_SUCCEEDED(mBoundThread
->IsOnCurrentThread(¤t
)));
387 THREADSAFETY_ASSERT(current
);
391 AssertActorDestroyed()
393 MOZ_ASSERT(mActorDestroyed
, "ChildImpl::ActorDestroy not called in time");
397 : mBoundThread(nullptr)
398 , mActorDestroyed(false)
400 AssertIsOnMainThread();
403 NS_INLINE_DECL_REFCOUNTING(ChildImpl
)
406 // Forwarded from BackgroundChild.
410 // Forwarded from BackgroundChild.
411 static PBackgroundChild
*
412 Alloc(Transport
* aTransport
, ProcessId aOtherProcess
);
414 // Forwarded from BackgroundChild.
415 static PBackgroundChild
*
416 GetForCurrentThread();
418 // Forwarded from BackgroundChild.
420 GetOrCreateForCurrentThread(nsIIPCBackgroundChildCreateCallback
* aCallback
);
422 // Forwarded from BackgroundChild.
424 CloseForCurrentThread();
426 // Forwarded from BackgroundChildImpl.
427 static BackgroundChildImpl::ThreadLocal
*
428 GetThreadLocalForCurrentThread();
431 ThreadLocalDestructor(void* aThreadLocal
)
433 auto threadLocalInfo
= static_cast<ThreadLocalInfo
*>(aThreadLocal
);
435 if (threadLocalInfo
) {
436 MOZ_ASSERT(threadLocalInfo
->mClosed
);
438 if (threadLocalInfo
->mActor
) {
439 threadLocalInfo
->mActor
->Close();
440 threadLocalInfo
->mActor
->AssertActorDestroyed();
442 // Since the actor is created on the main thread it must only
443 // be released on the main thread as well.
444 if (!NS_IsMainThread()) {
446 threadLocalInfo
->mActor
.forget(&actor
);
448 nsCOMPtr
<nsIRunnable
> releaser
=
449 NS_NewNonOwningRunnableMethod(actor
, &ChildImpl::Release
);
450 MOZ_ALWAYS_TRUE(NS_SUCCEEDED(NS_DispatchToMainThread(releaser
)));
453 delete threadLocalInfo
;
458 DispatchFailureCallback(nsIEventTarget
* aEventTarget
);
460 // This class is reference counted.
463 AssertActorDestroyed();
469 THREADSAFETY_ASSERT(!mBoundThread
);
471 #if defined(DEBUG) || !defined(RELEASE_BUILD)
472 mBoundThread
= NS_GetCurrentThread();
475 THREADSAFETY_ASSERT(mBoundThread
);
478 // Only called by IPDL.
480 ActorDestroy(ActorDestroyReason aWhy
) MOZ_OVERRIDE
;
482 static already_AddRefed
<nsIIPCBackgroundChildCreateCallback
>
486 // -----------------------------------------------------------------------------
487 // ParentImpl Helper Declarations
488 // -----------------------------------------------------------------------------
490 class ParentImpl::ShutdownObserver MOZ_FINAL
: public nsIObserver
495 AssertIsOnMainThread();
504 AssertIsOnMainThread();
508 class ParentImpl::RequestMessageLoopRunnable MOZ_FINAL
:
511 nsCOMPtr
<nsIThread
> mTargetThread
;
512 MessageLoop
* mMessageLoop
;
515 explicit RequestMessageLoopRunnable(nsIThread
* aTargetThread
)
516 : mTargetThread(aTargetThread
), mMessageLoop(nullptr)
518 AssertIsInMainProcess();
519 AssertIsOnMainThread();
520 MOZ_ASSERT(aTargetThread
);
523 NS_DECL_ISUPPORTS_INHERITED
526 ~RequestMessageLoopRunnable()
532 class ParentImpl::ShutdownBackgroundThreadRunnable MOZ_FINAL
: public nsRunnable
535 ShutdownBackgroundThreadRunnable()
537 AssertIsInMainProcess();
538 AssertIsOnMainThread();
541 NS_DECL_ISUPPORTS_INHERITED
544 ~ShutdownBackgroundThreadRunnable()
550 class ParentImpl::ForceCloseBackgroundActorsRunnable MOZ_FINAL
: public nsRunnable
552 nsTArray
<ParentImpl
*>* mActorArray
;
555 explicit ForceCloseBackgroundActorsRunnable(nsTArray
<ParentImpl
*>* aActorArray
)
556 : mActorArray(aActorArray
)
558 AssertIsInMainProcess();
559 AssertIsOnMainThread();
560 MOZ_ASSERT(aActorArray
);
563 NS_DECL_ISUPPORTS_INHERITED
566 ~ForceCloseBackgroundActorsRunnable()
572 class ParentImpl::CreateCallbackRunnable MOZ_FINAL
: public nsRunnable
574 nsRefPtr
<CreateCallback
> mCallback
;
577 explicit CreateCallbackRunnable(CreateCallback
* aCallback
)
578 : mCallback(aCallback
)
580 AssertIsInMainProcess();
581 AssertIsOnMainThread();
582 MOZ_ASSERT(aCallback
);
585 NS_DECL_ISUPPORTS_INHERITED
588 ~CreateCallbackRunnable()
594 class ParentImpl::ConnectActorRunnable MOZ_FINAL
: public nsRunnable
596 nsRefPtr
<ParentImpl
> mActor
;
597 Transport
* mTransport
;
598 ProcessHandle mProcessHandle
;
599 nsTArray
<ParentImpl
*>* mLiveActorArray
;
602 ConnectActorRunnable(ParentImpl
* aActor
,
603 Transport
* aTransport
,
604 ProcessHandle aProcessHandle
,
605 nsTArray
<ParentImpl
*>* aLiveActorArray
)
606 : mActor(aActor
), mTransport(aTransport
), mProcessHandle(aProcessHandle
),
607 mLiveActorArray(aLiveActorArray
)
609 AssertIsInMainProcess();
610 AssertIsOnMainThread();
612 MOZ_ASSERT(aTransport
);
613 MOZ_ASSERT(aLiveActorArray
);
616 NS_DECL_ISUPPORTS_INHERITED
619 ~ConnectActorRunnable()
621 AssertIsInMainProcess();
627 class NS_NO_VTABLE
ParentImpl::CreateCallback
630 NS_INLINE_DECL_REFCOUNTING(CreateCallback
)
633 Success(already_AddRefed
<ParentImpl
> aActor
, MessageLoop
* aMessageLoop
) = 0;
639 virtual ~CreateCallback()
643 // -----------------------------------------------------------------------------
644 // ChildImpl Helper Declarations
645 // -----------------------------------------------------------------------------
647 class ChildImpl::ShutdownObserver MOZ_FINAL
: public nsIObserver
652 AssertIsOnMainThread();
661 AssertIsOnMainThread();
665 class ChildImpl::CreateActorRunnable MOZ_FINAL
: public nsRunnable
667 nsCOMPtr
<nsIEventTarget
> mEventTarget
;
670 CreateActorRunnable()
671 : mEventTarget(NS_GetCurrentThread())
673 MOZ_ASSERT(mEventTarget
);
676 NS_DECL_ISUPPORTS_INHERITED
679 ~CreateActorRunnable()
685 class ChildImpl::ParentCreateCallback MOZ_FINAL
:
686 public ParentImpl::CreateCallback
688 nsCOMPtr
<nsIEventTarget
> mEventTarget
;
691 explicit ParentCreateCallback(nsIEventTarget
* aEventTarget
)
692 : mEventTarget(aEventTarget
)
694 AssertIsInMainProcess();
695 AssertIsOnMainThread();
696 MOZ_ASSERT(aEventTarget
);
700 ~ParentCreateCallback()
704 Success(already_AddRefed
<ParentImpl
> aActor
, MessageLoop
* aMessageLoop
)
708 Failure() MOZ_OVERRIDE
;
711 // Must be cancelable in order to dispatch on active worker threads
712 class ChildImpl::AlreadyCreatedCallbackRunnable MOZ_FINAL
:
713 public nsCancelableRunnable
716 AlreadyCreatedCallbackRunnable()
718 // May be created on any thread!
721 NS_DECL_ISUPPORTS_INHERITED
724 virtual ~AlreadyCreatedCallbackRunnable()
728 NS_DECL_NSICANCELABLERUNNABLE
731 class ChildImpl::FailedCreateCallbackRunnable MOZ_FINAL
: public nsRunnable
734 FailedCreateCallbackRunnable()
736 // May be created on any thread!
739 NS_DECL_ISUPPORTS_INHERITED
742 virtual ~FailedCreateCallbackRunnable()
748 class ChildImpl::OpenChildProcessActorRunnable MOZ_FINAL
: public nsRunnable
750 nsRefPtr
<ChildImpl
> mActor
;
751 nsAutoPtr
<Transport
> mTransport
;
752 ProcessHandle mProcessHandle
;
755 OpenChildProcessActorRunnable(already_AddRefed
<ChildImpl
>&& aActor
,
756 Transport
* aTransport
,
757 ProcessHandle aProcessHandle
)
758 : mActor(aActor
), mTransport(aTransport
),
759 mProcessHandle(aProcessHandle
)
761 AssertIsOnMainThread();
763 MOZ_ASSERT(aTransport
);
766 NS_DECL_ISUPPORTS_INHERITED
769 ~OpenChildProcessActorRunnable()
772 CRASH_IN_CHILD_PROCESS("Leaking transport!");
773 unused
<< mTransport
.forget();
780 class ChildImpl::OpenMainProcessActorRunnable MOZ_FINAL
: public nsRunnable
782 nsRefPtr
<ChildImpl
> mActor
;
783 nsRefPtr
<ParentImpl
> mParentActor
;
784 MessageLoop
* mParentMessageLoop
;
787 OpenMainProcessActorRunnable(already_AddRefed
<ChildImpl
>&& aChildActor
,
788 already_AddRefed
<ParentImpl
> aParentActor
,
789 MessageLoop
* aParentMessageLoop
)
790 : mActor(aChildActor
), mParentActor(aParentActor
),
791 mParentMessageLoop(aParentMessageLoop
)
793 AssertIsOnMainThread();
794 MOZ_ASSERT(mParentActor
);
795 MOZ_ASSERT(aParentMessageLoop
);
798 NS_DECL_ISUPPORTS_INHERITED
801 ~OpenMainProcessActorRunnable()
807 } // anonymous namespace
813 IsOnBackgroundThread()
815 return ParentImpl::IsOnBackgroundThread();
821 AssertIsOnBackgroundThread()
823 ParentImpl::AssertIsOnBackgroundThread();
829 } // namespace mozilla
831 // -----------------------------------------------------------------------------
832 // BackgroundParent Public Methods
833 // -----------------------------------------------------------------------------
837 BackgroundParent::IsOtherProcessActor(PBackgroundParent
* aBackgroundActor
)
839 return ParentImpl::IsOtherProcessActor(aBackgroundActor
);
843 already_AddRefed
<ContentParent
>
844 BackgroundParent::GetContentParent(PBackgroundParent
* aBackgroundActor
)
846 return ParentImpl::GetContentParent(aBackgroundActor
);
851 BackgroundParent::GetOrCreateActorForBlobImpl(
852 PBackgroundParent
* aBackgroundActor
,
855 AssertIsOnBackgroundThread();
856 MOZ_ASSERT(aBackgroundActor
);
857 MOZ_ASSERT(aBlobImpl
);
859 BlobParent
* actor
= BlobParent::GetOrCreate(aBackgroundActor
, aBlobImpl
);
860 if (NS_WARN_IF(!actor
)) {
869 BackgroundParent::GetRawContentParentForComparison(
870 PBackgroundParent
* aBackgroundActor
)
872 return ParentImpl::GetRawContentParentForComparison(aBackgroundActor
);
877 BackgroundParent::Alloc(ContentParent
* aContent
,
878 Transport
* aTransport
,
879 ProcessId aOtherProcess
)
881 return ParentImpl::Alloc(aContent
, aTransport
, aOtherProcess
);
884 // -----------------------------------------------------------------------------
885 // BackgroundChild Public Methods
886 // -----------------------------------------------------------------------------
890 BackgroundChild::Startup()
892 ChildImpl::Startup();
897 BackgroundChild::Alloc(Transport
* aTransport
, ProcessId aOtherProcess
)
899 return ChildImpl::Alloc(aTransport
, aOtherProcess
);
904 BackgroundChild::GetForCurrentThread()
906 return ChildImpl::GetForCurrentThread();
911 BackgroundChild::GetOrCreateForCurrentThread(
912 nsIIPCBackgroundChildCreateCallback
* aCallback
)
914 return ChildImpl::GetOrCreateForCurrentThread(aCallback
);
919 BackgroundChild::GetOrCreateActorForBlob(PBackgroundChild
* aBackgroundActor
,
922 MOZ_ASSERT(aBackgroundActor
);
924 MOZ_ASSERT(GetForCurrentThread(),
925 "BackgroundChild not created on this thread yet!");
926 MOZ_ASSERT(aBackgroundActor
== GetForCurrentThread(),
927 "BackgroundChild is bound to a different thread!");
929 nsRefPtr
<FileImpl
> blobImpl
= static_cast<File
*>(aBlob
)->Impl();
930 MOZ_ASSERT(blobImpl
);
932 BlobChild
* actor
= BlobChild::GetOrCreate(aBackgroundActor
, blobImpl
);
933 if (NS_WARN_IF(!actor
)) {
942 BackgroundChild::CloseForCurrentThread()
944 ChildImpl::CloseForCurrentThread();
947 // -----------------------------------------------------------------------------
948 // BackgroundChildImpl Public Methods
949 // -----------------------------------------------------------------------------
952 BackgroundChildImpl::ThreadLocal
*
953 BackgroundChildImpl::GetThreadLocalForCurrentThread()
955 return ChildImpl::GetThreadLocalForCurrentThread();
958 // -----------------------------------------------------------------------------
959 // ParentImpl Static Members
960 // -----------------------------------------------------------------------------
962 const ParentImpl::ProcessHandle
ParentImpl::kInvalidProcessHandle
=
964 ProcessHandle(INVALID_HANDLE_VALUE
);
969 StaticRefPtr
<nsIThread
> ParentImpl::sBackgroundThread
;
971 nsTArray
<ParentImpl
*>* ParentImpl::sLiveActorsForBackgroundThread
;
973 StaticRefPtr
<nsITimer
> ParentImpl::sShutdownTimer
;
975 Atomic
<PRThread
*> ParentImpl::sBackgroundPRThread
;
977 MessageLoop
* ParentImpl::sBackgroundThreadMessageLoop
= nullptr;
979 uint64_t ParentImpl::sLiveActorCount
= 0;
981 bool ParentImpl::sShutdownObserverRegistered
= false;
983 bool ParentImpl::sShutdownHasStarted
= false;
985 StaticAutoPtr
<nsTArray
<nsRefPtr
<ParentImpl::CreateCallback
>>>
986 ParentImpl::sPendingCallbacks
;
988 // -----------------------------------------------------------------------------
989 // ChildImpl Static Members
990 // -----------------------------------------------------------------------------
992 unsigned int ChildImpl::sThreadLocalIndex
= kBadThreadLocalIndex
;
994 StaticAutoPtr
<nsTArray
<nsCOMPtr
<nsIEventTarget
>>> ChildImpl::sPendingTargets
;
996 bool ChildImpl::sShutdownHasStarted
= false;
998 // -----------------------------------------------------------------------------
999 // ParentImpl Implementation
1000 // -----------------------------------------------------------------------------
1004 ParentImpl::IsOtherProcessActor(PBackgroundParent
* aBackgroundActor
)
1006 AssertIsOnBackgroundThread();
1007 MOZ_ASSERT(aBackgroundActor
);
1009 return static_cast<ParentImpl
*>(aBackgroundActor
)->mIsOtherProcessActor
;
1013 already_AddRefed
<ContentParent
>
1014 ParentImpl::GetContentParent(PBackgroundParent
* aBackgroundActor
)
1016 AssertIsOnBackgroundThread();
1017 MOZ_ASSERT(aBackgroundActor
);
1019 auto actor
= static_cast<ParentImpl
*>(aBackgroundActor
);
1020 if (actor
->mActorDestroyed
) {
1021 MOZ_ASSERT(false, "GetContentParent called after ActorDestroy was called!");
1025 if (actor
->mContent
) {
1026 // We need to hand out a reference to our ContentParent but we also need to
1027 // keep the one we have. We can't call AddRef here because ContentParent is
1028 // not threadsafe so instead we dispatch a runnable to the main thread to do
1029 // it for us. This is safe since we are guaranteed that our AddRef runnable
1030 // will run before the reference we hand out can be released, and the
1031 // ContentParent can't die as long as the existing reference is maintained.
1032 nsCOMPtr
<nsIRunnable
> runnable
=
1033 NS_NewNonOwningRunnableMethod(actor
->mContent
, &ContentParent::AddRef
);
1034 MOZ_ASSERT(runnable
);
1036 MOZ_ALWAYS_TRUE(NS_SUCCEEDED(NS_DispatchToMainThread(runnable
)));
1039 return already_AddRefed
<ContentParent
>(actor
->mContent
.get());
1044 ParentImpl::GetRawContentParentForComparison(
1045 PBackgroundParent
* aBackgroundActor
)
1047 AssertIsOnBackgroundThread();
1048 MOZ_ASSERT(aBackgroundActor
);
1050 auto actor
= static_cast<ParentImpl
*>(aBackgroundActor
);
1051 if (actor
->mActorDestroyed
) {
1053 "GetRawContentParentForComparison called after ActorDestroy was "
1055 return intptr_t(-1);
1058 return intptr_t(static_cast<nsIContentParent
*>(actor
->mContent
.get()));
1063 ParentImpl::Alloc(ContentParent
* aContent
,
1064 Transport
* aTransport
,
1065 ProcessId aOtherProcess
)
1067 AssertIsInMainProcess();
1068 AssertIsOnMainThread();
1069 MOZ_ASSERT(aTransport
);
1071 ProcessHandle processHandle
;
1072 if (!base::OpenProcessHandle(aOtherProcess
, &processHandle
)) {
1073 // Process has already died?
1077 if (!sBackgroundThread
&& !CreateBackgroundThread()) {
1078 NS_WARNING("Failed to create background thread!");
1082 MOZ_ASSERT(sLiveActorsForBackgroundThread
);
1086 nsRefPtr
<ParentImpl
> actor
= new ParentImpl(aContent
, aTransport
);
1088 nsCOMPtr
<nsIRunnable
> connectRunnable
=
1089 new ConnectActorRunnable(actor
, aTransport
, processHandle
,
1090 sLiveActorsForBackgroundThread
);
1092 if (NS_FAILED(sBackgroundThread
->Dispatch(connectRunnable
,
1093 NS_DISPATCH_NORMAL
))) {
1094 NS_WARNING("Failed to dispatch connect runnable!");
1096 MOZ_ASSERT(sLiveActorCount
);
1107 ParentImpl::CreateActorForSameProcess(CreateCallback
* aCallback
)
1109 AssertIsInMainProcess();
1110 AssertIsOnMainThread();
1111 MOZ_ASSERT(aCallback
);
1113 if (!sBackgroundThread
&& !CreateBackgroundThread()) {
1114 NS_WARNING("Failed to create background thread!");
1118 MOZ_ASSERT(!sShutdownHasStarted
);
1122 if (sBackgroundThreadMessageLoop
) {
1123 nsCOMPtr
<nsIRunnable
> callbackRunnable
=
1124 new CreateCallbackRunnable(aCallback
);
1125 MOZ_ALWAYS_TRUE(NS_SUCCEEDED(NS_DispatchToCurrentThread(callbackRunnable
)));
1129 if (!sPendingCallbacks
) {
1130 sPendingCallbacks
= new nsTArray
<nsRefPtr
<CreateCallback
>>();
1133 sPendingCallbacks
->AppendElement(aCallback
);
1139 ParentImpl::CreateBackgroundThread()
1141 AssertIsInMainProcess();
1142 AssertIsOnMainThread();
1143 MOZ_ASSERT(!sBackgroundThread
);
1144 MOZ_ASSERT(!sLiveActorsForBackgroundThread
);
1146 if (sShutdownHasStarted
) {
1147 NS_WARNING("Trying to create background thread after shutdown has "
1152 nsCOMPtr
<nsITimer
> newShutdownTimer
;
1154 if (!sShutdownTimer
) {
1156 newShutdownTimer
= do_CreateInstance(NS_TIMER_CONTRACTID
, &rv
);
1157 if (NS_WARN_IF(NS_FAILED(rv
))) {
1162 if (!sShutdownObserverRegistered
) {
1163 nsCOMPtr
<nsIObserverService
> obs
= services::GetObserverService();
1164 if (NS_WARN_IF(!obs
)) {
1168 nsCOMPtr
<nsIObserver
> observer
= new ShutdownObserver();
1171 obs
->AddObserver(observer
, NS_XPCOM_SHUTDOWN_THREADS_OBSERVER_ID
, false);
1172 if (NS_WARN_IF(NS_FAILED(rv
))) {
1176 sShutdownObserverRegistered
= true;
1179 nsCOMPtr
<nsIThread
> thread
;
1180 if (NS_FAILED(NS_NewNamedThread("IPDL Background", getter_AddRefs(thread
)))) {
1181 NS_WARNING("NS_NewNamedThread failed!");
1185 nsCOMPtr
<nsIRunnable
> messageLoopRunnable
=
1186 new RequestMessageLoopRunnable(thread
);
1187 if (NS_FAILED(thread
->Dispatch(messageLoopRunnable
, NS_DISPATCH_NORMAL
))) {
1188 NS_WARNING("Failed to dispatch RequestMessageLoopRunnable!");
1192 sBackgroundThread
= thread
;
1193 sLiveActorsForBackgroundThread
= new nsTArray
<ParentImpl
*>(1);
1195 if (!sShutdownTimer
) {
1196 MOZ_ASSERT(newShutdownTimer
);
1197 sShutdownTimer
= newShutdownTimer
;
1205 ParentImpl::ShutdownBackgroundThread()
1207 AssertIsInMainProcess();
1208 AssertIsOnMainThread();
1209 MOZ_ASSERT_IF(!sBackgroundThread
, !sBackgroundThreadMessageLoop
);
1210 MOZ_ASSERT(sShutdownHasStarted
);
1211 MOZ_ASSERT_IF(!sBackgroundThread
, !sLiveActorCount
);
1212 MOZ_ASSERT_IF(sBackgroundThread
, sShutdownTimer
);
1214 if (sPendingCallbacks
) {
1215 if (!sPendingCallbacks
->IsEmpty()) {
1216 nsTArray
<nsRefPtr
<CreateCallback
>> callbacks
;
1217 sPendingCallbacks
->SwapElements(callbacks
);
1219 for (uint32_t index
= 0; index
< callbacks
.Length(); index
++) {
1220 nsRefPtr
<CreateCallback
> callback
;
1221 callbacks
[index
].swap(callback
);
1222 MOZ_ASSERT(callback
);
1224 callback
->Failure();
1228 sPendingCallbacks
= nullptr;
1231 nsCOMPtr
<nsITimer
> shutdownTimer
= sShutdownTimer
.get();
1232 sShutdownTimer
= nullptr;
1234 if (sBackgroundThread
) {
1235 nsCOMPtr
<nsIThread
> thread
= sBackgroundThread
.get();
1236 sBackgroundThread
= nullptr;
1238 nsAutoPtr
<nsTArray
<ParentImpl
*>> liveActors(sLiveActorsForBackgroundThread
);
1239 sLiveActorsForBackgroundThread
= nullptr;
1241 sBackgroundThreadMessageLoop
= nullptr;
1243 MOZ_ASSERT_IF(!sShutdownHasStarted
, !sLiveActorCount
);
1245 if (sLiveActorCount
) {
1246 // We need to spin the event loop while we wait for all the actors to be
1247 // cleaned up. We also set a timeout to force-kill any hanging actors.
1248 TimerCallbackClosure
closure(thread
, liveActors
);
1250 MOZ_ALWAYS_TRUE(NS_SUCCEEDED(
1251 shutdownTimer
->InitWithFuncCallback(&ShutdownTimerCallback
,
1253 kShutdownTimerDelayMS
,
1254 nsITimer::TYPE_ONE_SHOT
)));
1256 nsIThread
* currentThread
= NS_GetCurrentThread();
1257 MOZ_ASSERT(currentThread
);
1259 while (sLiveActorCount
) {
1260 NS_ProcessNextEvent(currentThread
);
1263 MOZ_ASSERT(liveActors
->IsEmpty());
1265 MOZ_ALWAYS_TRUE(NS_SUCCEEDED(shutdownTimer
->Cancel()));
1268 // Dispatch this runnable to unregister the thread from the profiler.
1269 nsCOMPtr
<nsIRunnable
> shutdownRunnable
=
1270 new ShutdownBackgroundThreadRunnable();
1271 MOZ_ALWAYS_TRUE(NS_SUCCEEDED(thread
->Dispatch(shutdownRunnable
,
1272 NS_DISPATCH_NORMAL
)));
1274 MOZ_ALWAYS_TRUE(NS_SUCCEEDED(thread
->Shutdown()));
1280 ParentImpl::ShutdownTimerCallback(nsITimer
* aTimer
, void* aClosure
)
1282 AssertIsInMainProcess();
1283 AssertIsOnMainThread();
1284 MOZ_ASSERT(sShutdownHasStarted
);
1285 MOZ_ASSERT(sLiveActorCount
);
1287 auto closure
= static_cast<TimerCallbackClosure
*>(aClosure
);
1288 MOZ_ASSERT(closure
);
1290 // Don't let the stack unwind until the ForceCloseBackgroundActorsRunnable has
1294 nsCOMPtr
<nsIRunnable
> forceCloseRunnable
=
1295 new ForceCloseBackgroundActorsRunnable(closure
->mLiveActors
);
1296 MOZ_ALWAYS_TRUE(NS_SUCCEEDED(closure
->mThread
->Dispatch(forceCloseRunnable
,
1297 NS_DISPATCH_NORMAL
)));
1301 ParentImpl::Destroy()
1303 // May be called on any thread!
1305 AssertIsInMainProcess();
1307 nsCOMPtr
<nsIRunnable
> destroyRunnable
=
1308 NS_NewNonOwningRunnableMethod(this, &ParentImpl::MainThreadActorDestroy
);
1309 MOZ_ASSERT(destroyRunnable
);
1311 MOZ_ALWAYS_TRUE(NS_SUCCEEDED(NS_DispatchToMainThread(destroyRunnable
)));
1315 ParentImpl::MainThreadActorDestroy()
1317 AssertIsInMainProcess();
1318 AssertIsOnMainThread();
1319 MOZ_ASSERT_IF(mIsOtherProcessActor
, mContent
);
1320 MOZ_ASSERT_IF(!mIsOtherProcessActor
, !mContent
);
1321 MOZ_ASSERT_IF(mIsOtherProcessActor
, mTransport
);
1322 MOZ_ASSERT_IF(!mIsOtherProcessActor
, !mTransport
);
1325 XRE_GetIOMessageLoop()->PostTask(FROM_HERE
,
1326 new DeleteTask
<Transport
>(mTransport
));
1327 mTransport
= nullptr;
1330 ProcessHandle otherProcess
= OtherProcess();
1331 if (otherProcess
!= kInvalidProcessHandle
) {
1332 base::CloseProcessHandle(otherProcess
);
1334 SetOtherProcess(kInvalidProcessHandle
);
1340 MOZ_ASSERT(sLiveActorCount
);
1343 // This may be the last reference!
1348 ParentImpl::CloneToplevel(const InfallibleTArray
<ProtocolFdMapping
>& aFds
,
1349 ProcessHandle aPeerProcess
,
1350 ProtocolCloneContext
* aCtx
)
1352 AssertIsInMainProcess();
1353 AssertIsOnMainThread();
1354 MOZ_ASSERT(aCtx
->GetContentParent());
1356 const ProtocolId protocolId
= GetProtocolId();
1358 for (unsigned int i
= 0; i
< aFds
.Length(); i
++) {
1359 if (static_cast<ProtocolId
>(aFds
[i
].protocolId()) != protocolId
) {
1363 Transport
* transport
= OpenDescriptor(aFds
[i
].fd(),
1364 Transport::MODE_SERVER
);
1366 NS_WARNING("Failed to open transport!");
1370 PBackgroundParent
* clonedActor
=
1371 Alloc(aCtx
->GetContentParent(), transport
, base::GetProcId(aPeerProcess
));
1372 MOZ_ASSERT(clonedActor
);
1374 clonedActor
->CloneManagees(this, aCtx
);
1375 clonedActor
->SetTransport(transport
);
1384 ParentImpl::ActorDestroy(ActorDestroyReason aWhy
)
1386 AssertIsInMainProcess();
1387 AssertIsOnBackgroundThread();
1388 MOZ_ASSERT(!mActorDestroyed
);
1389 MOZ_ASSERT_IF(mIsOtherProcessActor
, mLiveActorArray
);
1391 BackgroundParentImpl::ActorDestroy(aWhy
);
1393 mActorDestroyed
= true;
1395 if (mLiveActorArray
) {
1396 MOZ_ALWAYS_TRUE(mLiveActorArray
->RemoveElement(this));
1397 mLiveActorArray
= nullptr;
1400 // This is tricky. We should be able to call Destroy() here directly because
1401 // we're not going to touch 'this' or our MessageChannel any longer on this
1402 // thread. Destroy() dispatches the MainThreadActorDestroy runnable and when
1403 // it runs it will destroy 'this' and our associated MessageChannel. However,
1404 // IPDL is about to call MessageChannel::Clear() on this thread! To avoid
1405 // racing with the main thread we must ensure that the MessageChannel lives
1406 // long enough to be cleared in this call stack.
1407 nsCOMPtr
<nsIRunnable
> destroyRunnable
=
1408 NS_NewNonOwningRunnableMethod(this, &ParentImpl::Destroy
);
1409 MOZ_ASSERT(destroyRunnable
);
1411 MOZ_ALWAYS_TRUE(NS_SUCCEEDED(NS_DispatchToCurrentThread(destroyRunnable
)));
1414 NS_IMPL_ISUPPORTS(ParentImpl::ShutdownObserver
, nsIObserver
)
1417 ParentImpl::ShutdownObserver::Observe(nsISupports
* aSubject
,
1419 const char16_t
* aData
)
1421 AssertIsInMainProcess();
1422 AssertIsOnMainThread();
1423 MOZ_ASSERT(!sShutdownHasStarted
);
1424 MOZ_ASSERT(!strcmp(aTopic
, NS_XPCOM_SHUTDOWN_THREADS_OBSERVER_ID
));
1426 sShutdownHasStarted
= true;
1428 // Do this first before calling (and spinning the event loop in)
1429 // ShutdownBackgroundThread().
1430 ChildImpl::Shutdown();
1432 ShutdownBackgroundThread();
1437 NS_IMPL_ISUPPORTS_INHERITED0(ParentImpl::RequestMessageLoopRunnable
,
1441 ParentImpl::RequestMessageLoopRunnable::Run()
1443 AssertIsInMainProcess();
1444 MOZ_ASSERT(mTargetThread
);
1446 char stackBaseGuess
;
1448 if (NS_IsMainThread()) {
1449 MOZ_ASSERT(mMessageLoop
);
1451 if (!sBackgroundThread
||
1452 !SameCOMIdentity(mTargetThread
.get(), sBackgroundThread
.get())) {
1456 MOZ_ASSERT(!sBackgroundThreadMessageLoop
);
1457 sBackgroundThreadMessageLoop
= mMessageLoop
;
1459 if (sPendingCallbacks
&& !sPendingCallbacks
->IsEmpty()) {
1460 nsTArray
<nsRefPtr
<CreateCallback
>> callbacks
;
1461 sPendingCallbacks
->SwapElements(callbacks
);
1463 for (uint32_t index
= 0; index
< callbacks
.Length(); index
++) {
1464 MOZ_ASSERT(callbacks
[index
]);
1466 nsCOMPtr
<nsIRunnable
> callbackRunnable
=
1467 new CreateCallbackRunnable(callbacks
[index
]);
1468 if (NS_FAILED(NS_DispatchToCurrentThread(callbackRunnable
))) {
1469 NS_WARNING("Failed to dispatch callback runnable!");
1477 profiler_register_thread("IPDL Background", &stackBaseGuess
);
1482 MOZ_ASSERT(NS_SUCCEEDED(mTargetThread
->IsOnCurrentThread(&correctThread
)));
1483 MOZ_ASSERT(correctThread
);
1487 DebugOnly
<PRThread
*> oldBackgroundThread
=
1488 sBackgroundPRThread
.exchange(PR_GetCurrentThread());
1490 MOZ_ASSERT_IF(oldBackgroundThread
,
1491 PR_GetCurrentThread() != oldBackgroundThread
);
1493 MOZ_ASSERT(!mMessageLoop
);
1495 mMessageLoop
= MessageLoop::current();
1496 MOZ_ASSERT(mMessageLoop
);
1498 if (NS_FAILED(NS_DispatchToMainThread(this))) {
1499 NS_WARNING("Failed to dispatch RequestMessageLoopRunnable to main thread!");
1500 return NS_ERROR_FAILURE
;
1506 NS_IMPL_ISUPPORTS_INHERITED0(ParentImpl::ShutdownBackgroundThreadRunnable
,
1510 ParentImpl::ShutdownBackgroundThreadRunnable::Run()
1512 AssertIsInMainProcess();
1514 // It is possible that another background thread was created while this thread
1515 // was shutting down. In that case we can't assert anything about
1516 // sBackgroundPRThread and we should not modify it here.
1517 sBackgroundPRThread
.compareExchange(PR_GetCurrentThread(), nullptr);
1519 profiler_unregister_thread();
1524 NS_IMPL_ISUPPORTS_INHERITED0(ParentImpl::ForceCloseBackgroundActorsRunnable
,
1528 ParentImpl::ForceCloseBackgroundActorsRunnable::Run()
1530 AssertIsInMainProcess();
1531 MOZ_ASSERT(mActorArray
);
1533 if (NS_IsMainThread()) {
1534 MOZ_ASSERT(sLiveActorCount
);
1539 AssertIsOnBackgroundThread();
1541 if (!mActorArray
->IsEmpty()) {
1542 // Copy the array since calling Close() could mutate the actual array.
1543 nsTArray
<ParentImpl
*> actorsToClose(*mActorArray
);
1545 for (uint32_t index
= 0; index
< actorsToClose
.Length(); index
++) {
1546 actorsToClose
[index
]->Close();
1550 MOZ_ALWAYS_TRUE(NS_SUCCEEDED(NS_DispatchToMainThread(this)));
1555 NS_IMPL_ISUPPORTS_INHERITED0(ParentImpl::CreateCallbackRunnable
, nsRunnable
)
1558 ParentImpl::CreateCallbackRunnable::Run()
1560 AssertIsInMainProcess();
1561 AssertIsOnMainThread();
1562 MOZ_ASSERT(sBackgroundThreadMessageLoop
);
1563 MOZ_ASSERT(mCallback
);
1565 nsRefPtr
<CreateCallback
> callback
;
1566 mCallback
.swap(callback
);
1568 nsRefPtr
<ParentImpl
> actor
= new ParentImpl();
1570 callback
->Success(actor
.forget(), sBackgroundThreadMessageLoop
);
1575 NS_IMPL_ISUPPORTS_INHERITED0(ParentImpl::ConnectActorRunnable
, nsRunnable
)
1578 ParentImpl::ConnectActorRunnable::Run()
1580 AssertIsInMainProcess();
1581 AssertIsOnBackgroundThread();
1583 // Transfer ownership to this thread. If Open() fails then we will release
1584 // this reference in Destroy.
1586 mActor
.forget(&actor
);
1588 if (!actor
->Open(mTransport
, mProcessHandle
, XRE_GetIOMessageLoop(),
1591 return NS_ERROR_FAILURE
;
1594 actor
->SetLiveActorArray(mLiveActorArray
);
1599 // -----------------------------------------------------------------------------
1600 // ChildImpl Implementation
1601 // -----------------------------------------------------------------------------
1605 ChildImpl::Startup()
1607 // This happens on the main thread but before XPCOM has started so we can't
1608 // assert that we're being called on the main thread here.
1610 MOZ_ASSERT(sThreadLocalIndex
== kBadThreadLocalIndex
,
1611 "BackgroundChild::Startup() called more than once!");
1614 PR_NewThreadPrivateIndex(&sThreadLocalIndex
, ThreadLocalDestructor
);
1615 MOZ_RELEASE_ASSERT(status
== PR_SUCCESS
, "PR_NewThreadPrivateIndex failed!");
1617 MOZ_ASSERT(sThreadLocalIndex
!= kBadThreadLocalIndex
);
1619 nsCOMPtr
<nsIObserverService
> observerService
= services::GetObserverService();
1620 MOZ_RELEASE_ASSERT(observerService
);
1622 nsCOMPtr
<nsIObserver
> observer
= new ShutdownObserver();
1625 observerService
->AddObserver(observer
,
1626 NS_XPCOM_SHUTDOWN_THREADS_OBSERVER_ID
,
1628 MOZ_RELEASE_ASSERT(NS_SUCCEEDED(rv
));
1633 ChildImpl::Shutdown()
1635 AssertIsOnMainThread();
1637 if (sShutdownHasStarted
) {
1638 MOZ_ASSERT_IF(sThreadLocalIndex
!= kBadThreadLocalIndex
,
1639 !PR_GetThreadPrivate(sThreadLocalIndex
));
1643 sShutdownHasStarted
= true;
1645 MOZ_ASSERT(sThreadLocalIndex
!= kBadThreadLocalIndex
);
1647 auto threadLocalInfo
=
1648 static_cast<ThreadLocalInfo
*>(PR_GetThreadPrivate(sThreadLocalIndex
));
1650 if (threadLocalInfo
) {
1651 MOZ_ASSERT(!threadLocalInfo
->mClosed
);
1652 threadLocalInfo
->mClosed
= true;
1655 DebugOnly
<PRStatus
> status
= PR_SetThreadPrivate(sThreadLocalIndex
, nullptr);
1656 MOZ_ASSERT(status
== PR_SUCCESS
);
1661 ChildImpl::Alloc(Transport
* aTransport
, ProcessId aOtherProcess
)
1663 AssertIsInChildProcess();
1664 AssertIsOnMainThread();
1665 MOZ_ASSERT(aTransport
);
1666 MOZ_ASSERT(sPendingTargets
);
1667 MOZ_ASSERT(!sPendingTargets
->IsEmpty());
1669 nsCOMPtr
<nsIEventTarget
> eventTarget
;
1670 sPendingTargets
->ElementAt(0).swap(eventTarget
);
1672 sPendingTargets
->RemoveElementAt(0);
1674 ProcessHandle processHandle
;
1675 if (!base::OpenProcessHandle(aOtherProcess
, &processHandle
)) {
1676 MOZ_CRASH("Failed to open process handle!");
1679 nsRefPtr
<ChildImpl
> actor
= new ChildImpl();
1681 ChildImpl
* weakActor
= actor
;
1683 nsCOMPtr
<nsIRunnable
> openRunnable
=
1684 new OpenChildProcessActorRunnable(actor
.forget(), aTransport
,
1686 if (NS_FAILED(eventTarget
->Dispatch(openRunnable
, NS_DISPATCH_NORMAL
))) {
1687 MOZ_CRASH("Failed to dispatch OpenActorRunnable!");
1690 // This value is only checked against null to determine success/failure, so
1691 // there is no need to worry about the reference count here.
1697 ChildImpl::GetForCurrentThread()
1699 MOZ_ASSERT(sThreadLocalIndex
!= kBadThreadLocalIndex
);
1701 auto threadLocalInfo
=
1702 static_cast<ThreadLocalInfo
*>(PR_GetThreadPrivate(sThreadLocalIndex
));
1704 if (!threadLocalInfo
) {
1708 return threadLocalInfo
->mActor
;
1713 ChildImpl::GetOrCreateForCurrentThread(
1714 nsIIPCBackgroundChildCreateCallback
* aCallback
)
1716 MOZ_ASSERT(aCallback
);
1717 MOZ_ASSERT(sThreadLocalIndex
!= kBadThreadLocalIndex
,
1718 "BackgroundChild::Startup() was never called!");
1720 bool created
= false;
1722 auto threadLocalInfo
=
1723 static_cast<ThreadLocalInfo
*>(PR_GetThreadPrivate(sThreadLocalIndex
));
1725 if (threadLocalInfo
) {
1726 threadLocalInfo
->mCallbacks
.AppendElement(aCallback
);
1728 nsAutoPtr
<ThreadLocalInfo
> newInfo(new ThreadLocalInfo(aCallback
));
1730 if (PR_SetThreadPrivate(sThreadLocalIndex
, newInfo
) != PR_SUCCESS
) {
1731 CRASH_IN_CHILD_PROCESS("PR_SetThreadPrivate failed!");
1736 threadLocalInfo
= newInfo
.forget();
1739 if (threadLocalInfo
->mActor
) {
1740 // Runnable will use GetForCurrentThread() to retrieve actor again. This
1741 // allows us to avoid addref'ing on the wrong thread.
1742 nsCOMPtr
<nsIRunnable
> runnable
= new AlreadyCreatedCallbackRunnable();
1743 MOZ_ALWAYS_TRUE(NS_SUCCEEDED(NS_DispatchToCurrentThread(runnable
)));
1749 // We have already started the sequence for opening the actor so there's
1750 // nothing else we need to do here. This callback will be called after the
1751 // first callback in the schedule runnable.
1755 if (NS_IsMainThread()) {
1756 if (NS_WARN_IF(!OpenProtocolOnMainThread(NS_GetCurrentThread()))) {
1763 nsRefPtr
<CreateActorRunnable
> runnable
= new CreateActorRunnable();
1764 if (NS_FAILED(NS_DispatchToMainThread(runnable
))) {
1765 CRASH_IN_CHILD_PROCESS("Failed to dispatch to main thread!");
1774 ChildImpl::CloseForCurrentThread()
1776 MOZ_ASSERT(sThreadLocalIndex
!= kBadThreadLocalIndex
,
1777 "BackgroundChild::Startup() was never called!");
1778 auto threadLocalInfo
=
1779 static_cast<ThreadLocalInfo
*>(PR_GetThreadPrivate(sThreadLocalIndex
));
1781 if (!threadLocalInfo
) {
1785 MOZ_ASSERT(!threadLocalInfo
->mClosed
);
1786 threadLocalInfo
->mClosed
= true;
1788 if (threadLocalInfo
->mActor
) {
1789 threadLocalInfo
->mActor
->FlushPendingInterruptQueue();
1792 // Clearing the thread local will synchronously close the actor.
1793 DebugOnly
<PRStatus
> status
= PR_SetThreadPrivate(sThreadLocalIndex
, nullptr);
1794 MOZ_ASSERT(status
== PR_SUCCESS
);
1798 BackgroundChildImpl::ThreadLocal
*
1799 ChildImpl::GetThreadLocalForCurrentThread()
1801 MOZ_ASSERT(sThreadLocalIndex
!= kBadThreadLocalIndex
,
1802 "BackgroundChild::Startup() was never called!");
1804 auto threadLocalInfo
=
1805 static_cast<ThreadLocalInfo
*>(PR_GetThreadPrivate(sThreadLocalIndex
));
1807 if (!threadLocalInfo
) {
1811 if (!threadLocalInfo
->mConsumerThreadLocal
) {
1812 threadLocalInfo
->mConsumerThreadLocal
=
1813 new BackgroundChildImpl::ThreadLocal();
1816 return threadLocalInfo
->mConsumerThreadLocal
;
1820 already_AddRefed
<nsIIPCBackgroundChildCreateCallback
>
1821 ChildImpl::GetNextCallback()
1823 // May run on any thread!
1825 auto threadLocalInfo
=
1826 static_cast<ThreadLocalInfo
*>(PR_GetThreadPrivate(sThreadLocalIndex
));
1827 MOZ_ASSERT(threadLocalInfo
);
1829 if (threadLocalInfo
->mCallbacks
.IsEmpty()) {
1833 nsCOMPtr
<nsIIPCBackgroundChildCreateCallback
> callback
;
1834 threadLocalInfo
->mCallbacks
[0].swap(callback
);
1836 threadLocalInfo
->mCallbacks
.RemoveElementAt(0);
1838 return callback
.forget();
1841 NS_IMPL_ISUPPORTS_INHERITED0(ChildImpl::AlreadyCreatedCallbackRunnable
,
1842 nsCancelableRunnable
)
1845 ChildImpl::AlreadyCreatedCallbackRunnable::Run()
1847 // May run on any thread!
1849 // Report the current actor back in the callback.
1850 PBackgroundChild
* actor
= ChildImpl::GetForCurrentThread();
1852 // If the current actor is null, do not create a new actor here. This likely
1853 // means we are in the process of cleaning up a worker thread and do not want
1854 // a new actor created. Unfortunately we cannot report back to the callback
1855 // because the thread local is gone at this point. Instead simply do nothing
1857 if (NS_WARN_IF(!actor
)) {
1861 nsCOMPtr
<nsIIPCBackgroundChildCreateCallback
> callback
=
1862 ChildImpl::GetNextCallback();
1864 callback
->ActorCreated(actor
);
1865 callback
= ChildImpl::GetNextCallback();
1872 ChildImpl::AlreadyCreatedCallbackRunnable::Cancel()
1874 // These are IPC infrastructure objects and need to run unconditionally.
1879 NS_IMPL_ISUPPORTS_INHERITED0(ChildImpl::FailedCreateCallbackRunnable
,
1883 ChildImpl::FailedCreateCallbackRunnable::Run()
1885 // May run on any thread!
1887 nsCOMPtr
<nsIIPCBackgroundChildCreateCallback
> callback
=
1888 ChildImpl::GetNextCallback();
1890 callback
->ActorFailed();
1891 callback
= ChildImpl::GetNextCallback();
1897 NS_IMPL_ISUPPORTS_INHERITED0(ChildImpl::OpenChildProcessActorRunnable
,
1901 ChildImpl::OpenChildProcessActorRunnable::Run()
1903 // May be run on any thread!
1905 AssertIsInChildProcess();
1907 MOZ_ASSERT(mTransport
);
1909 nsCOMPtr
<nsIIPCBackgroundChildCreateCallback
> callback
=
1910 ChildImpl::GetNextCallback();
1911 MOZ_ASSERT(callback
,
1912 "There should be at least one callback when first creating the "
1915 nsRefPtr
<ChildImpl
> strongActor
;
1916 mActor
.swap(strongActor
);
1918 if (!strongActor
->Open(mTransport
.forget(), mProcessHandle
,
1919 XRE_GetIOMessageLoop(), ChildSide
)) {
1920 CRASH_IN_CHILD_PROCESS("Failed to open ChildImpl!");
1923 callback
->ActorFailed();
1924 callback
= ChildImpl::GetNextCallback();
1930 // Now that Open() has succeeded transfer the ownership of the actor to IPDL.
1931 auto threadLocalInfo
=
1932 static_cast<ThreadLocalInfo
*>(PR_GetThreadPrivate(sThreadLocalIndex
));
1934 MOZ_ASSERT(threadLocalInfo
);
1935 MOZ_ASSERT(!threadLocalInfo
->mActor
);
1937 nsRefPtr
<ChildImpl
>& actor
= threadLocalInfo
->mActor
;
1938 strongActor
.swap(actor
);
1940 actor
->SetBoundThread();
1943 callback
->ActorCreated(actor
);
1944 callback
= ChildImpl::GetNextCallback();
1950 NS_IMPL_ISUPPORTS_INHERITED0(ChildImpl::OpenMainProcessActorRunnable
,
1954 ChildImpl::OpenMainProcessActorRunnable::Run()
1956 // May run on any thread!
1958 AssertIsInMainProcess();
1960 MOZ_ASSERT(mParentActor
);
1961 MOZ_ASSERT(mParentMessageLoop
);
1963 nsCOMPtr
<nsIIPCBackgroundChildCreateCallback
> callback
=
1964 ChildImpl::GetNextCallback();
1965 MOZ_ASSERT(callback
,
1966 "There should be at least one callback when first creating the "
1969 nsRefPtr
<ChildImpl
> strongChildActor
;
1970 mActor
.swap(strongChildActor
);
1972 nsRefPtr
<ParentImpl
> parentActor
;
1973 mParentActor
.swap(parentActor
);
1975 MessageChannel
* parentChannel
= parentActor
->GetIPCChannel();
1976 MOZ_ASSERT(parentChannel
);
1978 if (!strongChildActor
->Open(parentChannel
, mParentMessageLoop
, ChildSide
)) {
1979 NS_WARNING("Failed to open ChildImpl!");
1981 parentActor
->Destroy();
1984 callback
->ActorFailed();
1985 callback
= ChildImpl::GetNextCallback();
1991 // Now that Open() has succeeded transfer the ownership of the actors to IPDL.
1992 unused
<< parentActor
.forget();
1994 auto threadLocalInfo
=
1995 static_cast<ThreadLocalInfo
*>(PR_GetThreadPrivate(sThreadLocalIndex
));
1997 MOZ_ASSERT(threadLocalInfo
);
1998 MOZ_ASSERT(!threadLocalInfo
->mActor
);
2000 nsRefPtr
<ChildImpl
>& childActor
= threadLocalInfo
->mActor
;
2001 strongChildActor
.swap(childActor
);
2003 childActor
->SetBoundThread();
2006 callback
->ActorCreated(childActor
);
2007 callback
= ChildImpl::GetNextCallback();
2013 NS_IMPL_ISUPPORTS_INHERITED0(ChildImpl::CreateActorRunnable
, nsRunnable
)
2016 ChildImpl::CreateActorRunnable::Run()
2018 AssertIsOnMainThread();
2020 if (!OpenProtocolOnMainThread(mEventTarget
)) {
2021 NS_WARNING("OpenProtocolOnMainThread failed!");
2022 return NS_ERROR_FAILURE
;
2029 ChildImpl::ParentCreateCallback::Success(
2030 already_AddRefed
<ParentImpl
> aParentActor
,
2031 MessageLoop
* aParentMessageLoop
)
2033 AssertIsInMainProcess();
2034 AssertIsOnMainThread();
2036 nsRefPtr
<ParentImpl
> parentActor
= aParentActor
;
2037 MOZ_ASSERT(parentActor
);
2038 MOZ_ASSERT(aParentMessageLoop
);
2039 MOZ_ASSERT(mEventTarget
);
2041 nsRefPtr
<ChildImpl
> childActor
= new ChildImpl();
2043 nsCOMPtr
<nsIEventTarget
> target
;
2044 mEventTarget
.swap(target
);
2046 nsCOMPtr
<nsIRunnable
> openRunnable
=
2047 new OpenMainProcessActorRunnable(childActor
.forget(), parentActor
.forget(),
2048 aParentMessageLoop
);
2049 if (NS_FAILED(target
->Dispatch(openRunnable
, NS_DISPATCH_NORMAL
))) {
2050 NS_WARNING("Failed to dispatch open runnable!");
2055 ChildImpl::ParentCreateCallback::Failure()
2057 AssertIsInMainProcess();
2058 AssertIsOnMainThread();
2059 MOZ_ASSERT(mEventTarget
);
2061 nsCOMPtr
<nsIEventTarget
> target
;
2062 mEventTarget
.swap(target
);
2064 DispatchFailureCallback(target
);
2069 ChildImpl::OpenProtocolOnMainThread(nsIEventTarget
* aEventTarget
)
2071 AssertIsOnMainThread();
2072 MOZ_ASSERT(aEventTarget
);
2074 if (sShutdownHasStarted
) {
2075 MOZ_CRASH("Called BackgroundChild::GetOrCreateForCurrentThread after "
2076 "shutdown has started!");
2079 if (IsMainProcess()) {
2080 nsRefPtr
<ParentImpl::CreateCallback
> parentCallback
=
2081 new ParentCreateCallback(aEventTarget
);
2083 if (!ParentImpl::CreateActorForSameProcess(parentCallback
)) {
2084 NS_WARNING("BackgroundParent::CreateActor() failed!");
2085 DispatchFailureCallback(aEventTarget
);
2092 ContentChild
* content
= ContentChild::GetSingleton();
2093 MOZ_ASSERT(content
);
2095 if (!PBackground::Open(content
)) {
2096 MOZ_CRASH("Failed to create top level actor!");
2100 if (!sPendingTargets
) {
2101 sPendingTargets
= new nsTArray
<nsCOMPtr
<nsIEventTarget
>>(1);
2102 ClearOnShutdown(&sPendingTargets
);
2105 sPendingTargets
->AppendElement(aEventTarget
);
2112 ChildImpl::DispatchFailureCallback(nsIEventTarget
* aEventTarget
)
2114 MOZ_ASSERT(aEventTarget
);
2116 nsCOMPtr
<nsIRunnable
> callbackRunnable
= new FailedCreateCallbackRunnable();
2117 if (NS_FAILED(aEventTarget
->Dispatch(callbackRunnable
, NS_DISPATCH_NORMAL
))) {
2118 NS_WARNING("Failed to dispatch CreateCallbackRunnable!");
2123 ChildImpl::ActorDestroy(ActorDestroyReason aWhy
)
2125 AssertIsOnBoundThread();
2127 MOZ_ASSERT(!mActorDestroyed
);
2128 mActorDestroyed
= true;
2130 BackgroundChildImpl::ActorDestroy(aWhy
);
2133 NS_IMPL_ISUPPORTS(ChildImpl::ShutdownObserver
, nsIObserver
)
2136 ChildImpl::ShutdownObserver::Observe(nsISupports
* aSubject
,
2138 const char16_t
* aData
)
2140 AssertIsOnMainThread();
2141 MOZ_ASSERT(!strcmp(aTopic
, NS_XPCOM_SHUTDOWN_THREADS_OBSERVER_ID
));
2143 ChildImpl::Shutdown();