Wed, 31 Dec 2014 06:09:35 +0100
Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.
1 #include "TestInterruptErrorCleanup.h"
3 #include "mozilla/CondVar.h"
4 #include "mozilla/Mutex.h"
6 #include "IPDLUnitTests.h" // fail etc.
7 #include "IPDLUnitTestSubprocess.h"
9 using mozilla::CondVar;
10 using mozilla::Mutex;
11 using mozilla::MutexAutoLock;
13 namespace mozilla {
14 namespace _ipdltest {
16 //-----------------------------------------------------------------------------
17 // parent
19 namespace {
21 // NB: this test does its own shutdown, rather than going through
22 // QuitParent(), because it's testing degenerate edge cases
24 void DeleteSubprocess(Mutex* mutex, CondVar* cvar)
25 {
26 MutexAutoLock lock(*mutex);
28 delete gSubprocess;
29 gSubprocess = nullptr;
31 cvar->Notify();
32 }
34 void DeleteTheWorld()
35 {
36 delete static_cast<TestInterruptErrorCleanupParent*>(gParentActor);
37 gParentActor = nullptr;
39 // needs to be synchronous to avoid affecting event ordering on
40 // the main thread
41 Mutex mutex("TestInterruptErrorCleanup.DeleteTheWorld.mutex");
42 CondVar cvar(mutex, "TestInterruptErrorCleanup.DeleteTheWorld.cvar");
44 MutexAutoLock lock(mutex);
46 XRE_GetIOMessageLoop()->PostTask(
47 FROM_HERE,
48 NewRunnableFunction(DeleteSubprocess, &mutex, &cvar));
50 cvar.Wait();
51 }
53 void Done()
54 {
55 static NS_DEFINE_CID(kAppShellCID, NS_APPSHELL_CID);
56 nsCOMPtr<nsIAppShell> appShell (do_GetService(kAppShellCID));
57 appShell->Exit();
59 passed(__FILE__);
60 }
62 } // namespace <anon>
64 TestInterruptErrorCleanupParent::TestInterruptErrorCleanupParent()
65 : mGotProcessingError(false)
66 {
67 MOZ_COUNT_CTOR(TestInterruptErrorCleanupParent);
68 }
70 TestInterruptErrorCleanupParent::~TestInterruptErrorCleanupParent()
71 {
72 MOZ_COUNT_DTOR(TestInterruptErrorCleanupParent);
73 }
75 void
76 TestInterruptErrorCleanupParent::Main()
77 {
78 // This test models the following sequence of events
79 //
80 // (1) Parent: Interrupt out-call
81 // (2) Child: crash
82 // --[Parent-only hereafter]--
83 // (3) Interrupt out-call return false
84 // (4) Close()
85 // --[event loop]--
86 // (5) delete parentActor
87 // (6) delete childProcess
88 // --[event loop]--
89 // (7) Channel::OnError notification
90 // --[event loop]--
91 // (8) Done, quit
92 //
93 // See bug 535298 and friends; this seqeunce of events captures
94 // three differnent potential errors
95 // - Close()-after-error (semantic error previously)
96 // - use-after-free of parentActor
97 // - use-after-free of channel
98 //
99 // Because of legacy constraints related to nsNPAPI* code, we need
100 // to ensure that this sequence of events can occur without
101 // errors/crashes.
103 MessageLoop::current()->PostTask(
104 FROM_HERE, NewRunnableFunction(DeleteTheWorld));
106 // it's a failure if this *succeeds*
107 if (CallError())
108 fail("expected an error!");
110 if (!mGotProcessingError)
111 fail("expected a ProcessingError() notification");
113 // it's OK to Close() a channel after an error, because nsNPAPI*
114 // wants to do this
115 Close();
117 // we know that this event *must* be after the MaybeError
118 // notification enqueued by AsyncChannel, because that event is
119 // enqueued within the same mutex that ends up signaling the
120 // wakeup-on-error of |CallError()| above
121 MessageLoop::current()->PostTask(FROM_HERE, NewRunnableFunction(Done));
122 }
124 void
125 TestInterruptErrorCleanupParent::ProcessingError(Result what)
126 {
127 if (what != MsgDropped)
128 fail("unexpected processing error");
129 mGotProcessingError = true;
130 }
132 //-----------------------------------------------------------------------------
133 // child
135 TestInterruptErrorCleanupChild::TestInterruptErrorCleanupChild()
136 {
137 MOZ_COUNT_CTOR(TestInterruptErrorCleanupChild);
138 }
140 TestInterruptErrorCleanupChild::~TestInterruptErrorCleanupChild()
141 {
142 MOZ_COUNT_DTOR(TestInterruptErrorCleanupChild);
143 }
145 bool
146 TestInterruptErrorCleanupChild::AnswerError()
147 {
148 _exit(0);
149 NS_RUNTIMEABORT("unreached");
150 return false;
151 }
154 } // namespace _ipdltest
155 } // namespace mozilla