ipc/ipdl/test/cxx/TestInterruptShutdownRace.cpp

branch
TOR_BUG_9701
changeset 15
b8a032363ba2
equal deleted inserted replaced
-1:000000000000 0:ac54a7b054c5
1 #include "TestInterruptShutdownRace.h"
2
3 #include "IPDLUnitTests.h" // fail etc.
4 #include "IPDLUnitTestSubprocess.h"
5
6 template<>
7 struct RunnableMethodTraits<mozilla::_ipdltest::TestInterruptShutdownRaceParent>
8 {
9 static void RetainCallee(mozilla::_ipdltest::TestInterruptShutdownRaceParent* obj) { }
10 static void ReleaseCallee(mozilla::_ipdltest::TestInterruptShutdownRaceParent* obj) { }
11 };
12
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()
26 {
27 delete gSubprocess;
28 gSubprocess = nullptr;
29 }
30
31 void Done()
32 {
33 passed(__FILE__);
34 QuitParent();
35 }
36
37 } // namespace <anon>
38
39 TestInterruptShutdownRaceParent::TestInterruptShutdownRaceParent()
40 {
41 MOZ_COUNT_CTOR(TestInterruptShutdownRaceParent);
42 }
43
44 TestInterruptShutdownRaceParent::~TestInterruptShutdownRaceParent()
45 {
46 MOZ_COUNT_DTOR(TestInterruptShutdownRaceParent);
47 }
48
49 void
50 TestInterruptShutdownRaceParent::Main()
51 {
52 if (!SendStart())
53 fail("sending Start");
54 }
55
56 bool
57 TestInterruptShutdownRaceParent::RecvStartDeath()
58 {
59 // this will be ordered before the OnMaybeDequeueOne event of
60 // Orphan in the queue
61 MessageLoop::current()->PostTask(
62 FROM_HERE,
63 NewRunnableMethod(this,
64 &TestInterruptShutdownRaceParent::StartShuttingDown));
65 return true;
66 }
67
68 void
69 TestInterruptShutdownRaceParent::StartShuttingDown()
70 {
71 // NB: we sleep here to try and avoid receiving the Orphan message
72 // while waiting for the CallExit() reply. if we fail at that, it
73 // will cause the test to pass spuriously, because there won't be
74 // an OnMaybeDequeueOne task for Orphan
75 PR_Sleep(2000);
76
77 if (CallExit())
78 fail("connection was supposed to be interrupted");
79
80 Close();
81
82 delete static_cast<TestInterruptShutdownRaceParent*>(gParentActor);
83 gParentActor = nullptr;
84
85 XRE_GetIOMessageLoop()->PostTask(FROM_HERE,
86 NewRunnableFunction(DeleteSubprocess));
87
88 // this is ordered after the OnMaybeDequeueOne event in the queue
89 MessageLoop::current()->PostTask(FROM_HERE,
90 NewRunnableFunction(Done));
91
92 // |this| has been deleted, be mindful
93 }
94
95 bool
96 TestInterruptShutdownRaceParent::RecvOrphan()
97 {
98 // it would be nice to fail() here, but we'll process this message
99 // while waiting for the reply CallExit(). The OnMaybeDequeueOne
100 // task will still be in the queue, it just wouldn't have had any
101 // work to do, if we hadn't deleted ourself
102 return true;
103 }
104
105 //-----------------------------------------------------------------------------
106 // child
107
108 TestInterruptShutdownRaceChild::TestInterruptShutdownRaceChild()
109 {
110 MOZ_COUNT_CTOR(TestInterruptShutdownRaceChild);
111 }
112
113 TestInterruptShutdownRaceChild::~TestInterruptShutdownRaceChild()
114 {
115 MOZ_COUNT_DTOR(TestInterruptShutdownRaceChild);
116 }
117
118 bool
119 TestInterruptShutdownRaceChild::RecvStart()
120 {
121 if (!SendStartDeath())
122 fail("sending StartDeath");
123
124 // See comment in StartShuttingDown(): we want to send Orphan()
125 // while the parent is in its PR_Sleep()
126 PR_Sleep(1000);
127
128 if (!SendOrphan())
129 fail("sending Orphan");
130
131 return true;
132 }
133
134 bool
135 TestInterruptShutdownRaceChild::AnswerExit()
136 {
137 _exit(0);
138 NS_RUNTIMEABORT("unreached");
139 return false;
140 }
141
142
143 } // namespace _ipdltest
144 } // namespace mozilla

mercurial