1 #include "TestCrashCleanup.h"
2 
3 #include "base/task.h"
4 #include "mozilla/CondVar.h"
5 #include "mozilla/Mutex.h"
6 
7 #include "IPDLUnitTests.h"      // fail etc.
8 #include "IPDLUnitTestSubprocess.h"
9 
10 using mozilla::CondVar;
11 using mozilla::Mutex;
12 using mozilla::MutexAutoLock;
13 
14 namespace mozilla {
15 namespace _ipdltest {
16 
17 //-----------------------------------------------------------------------------
18 // parent
19 
20 namespace {
21 
22 // NB: this test does its own shutdown, rather than going through
23 // QuitParent(), because it's testing degenerate edge cases
24 
25 void DeleteSubprocess(Mutex* mutex, CondVar* cvar)
26 {
27     MutexAutoLock lock(*mutex);
28 
29     delete gSubprocess;
30     gSubprocess = nullptr;
31 
32     cvar->Notify();
33 }
34 
35 void DeleteTheWorld()
36 {
37     delete static_cast<TestCrashCleanupParent*>(gParentActor);
38     gParentActor = nullptr;
39 
40     // needs to be synchronous to avoid affecting event ordering on
41     // the main thread
42     Mutex mutex("TestCrashCleanup.DeleteTheWorld.mutex");
43     CondVar cvar(mutex, "TestCrashCleanup.DeleteTheWorld.cvar");
44 
45     MutexAutoLock lock(mutex);
46 
47     XRE_GetIOMessageLoop()->PostTask(
48       NewRunnableFunction(DeleteSubprocess, &mutex, &cvar));
49 
50     cvar.Wait();
51 }
52 
53 void Done()
54 {
55   static NS_DEFINE_CID(kAppShellCID, NS_APPSHELL_CID);
56   nsCOMPtr<nsIAppShell> appShell (do_GetService(kAppShellCID));
57   appShell->Exit();
58 
59   passed(__FILE__);
60 }
61 
62 } // namespace <anon>
63 
64 TestCrashCleanupParent::TestCrashCleanupParent() : mCleanedUp(false)
65 {
66     MOZ_COUNT_CTOR(TestCrashCleanupParent);
67 }
68 
69 TestCrashCleanupParent::~TestCrashCleanupParent()
70 {
71     MOZ_COUNT_DTOR(TestCrashCleanupParent);
72 
73     if (!mCleanedUp)
74         fail("should have been ActorDestroy()d!");
75 }
76 
77 void
78 TestCrashCleanupParent::Main()
79 {
80     // NB: has to be enqueued before IO thread's error notification
81     MessageLoop::current()->PostTask(
82         NewRunnableFunction(DeleteTheWorld));
83 
84     if (CallDIEDIEDIE())
85         fail("expected an error!");
86 
87     Close();
88 
89     MessageLoop::current()->PostTask(NewRunnableFunction(Done));
90 }
91 
92 
93 //-----------------------------------------------------------------------------
94 // child
95 
96 TestCrashCleanupChild::TestCrashCleanupChild()
97 {
98     MOZ_COUNT_CTOR(TestCrashCleanupChild);
99 }
100 
101 TestCrashCleanupChild::~TestCrashCleanupChild()
102 {
103     MOZ_COUNT_DTOR(TestCrashCleanupChild);
104 }
105 
106 bool
107 TestCrashCleanupChild::AnswerDIEDIEDIE()
108 {
109     _exit(0);
110     NS_RUNTIMEABORT("unreached");
111     return false;
112 }
113 
114 
115 } // namespace _ipdltest
116 } // namespace mozilla
117