1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/ipc/ipdl/test/cxx/TestInterruptShutdownRace.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,144 @@ 1.4 +#include "TestInterruptShutdownRace.h" 1.5 + 1.6 +#include "IPDLUnitTests.h" // fail etc. 1.7 +#include "IPDLUnitTestSubprocess.h" 1.8 + 1.9 +template<> 1.10 +struct RunnableMethodTraits<mozilla::_ipdltest::TestInterruptShutdownRaceParent> 1.11 +{ 1.12 + static void RetainCallee(mozilla::_ipdltest::TestInterruptShutdownRaceParent* obj) { } 1.13 + static void ReleaseCallee(mozilla::_ipdltest::TestInterruptShutdownRaceParent* obj) { } 1.14 +}; 1.15 + 1.16 + 1.17 +namespace mozilla { 1.18 +namespace _ipdltest { 1.19 + 1.20 +//----------------------------------------------------------------------------- 1.21 +// parent 1.22 + 1.23 +namespace { 1.24 + 1.25 +// NB: this test does its own shutdown, rather than going through 1.26 +// QuitParent(), because it's testing degenerate edge cases 1.27 + 1.28 +void DeleteSubprocess() 1.29 +{ 1.30 + delete gSubprocess; 1.31 + gSubprocess = nullptr; 1.32 +} 1.33 + 1.34 +void Done() 1.35 +{ 1.36 + passed(__FILE__); 1.37 + QuitParent(); 1.38 +} 1.39 + 1.40 +} // namespace <anon> 1.41 + 1.42 +TestInterruptShutdownRaceParent::TestInterruptShutdownRaceParent() 1.43 +{ 1.44 + MOZ_COUNT_CTOR(TestInterruptShutdownRaceParent); 1.45 +} 1.46 + 1.47 +TestInterruptShutdownRaceParent::~TestInterruptShutdownRaceParent() 1.48 +{ 1.49 + MOZ_COUNT_DTOR(TestInterruptShutdownRaceParent); 1.50 +} 1.51 + 1.52 +void 1.53 +TestInterruptShutdownRaceParent::Main() 1.54 +{ 1.55 + if (!SendStart()) 1.56 + fail("sending Start"); 1.57 +} 1.58 + 1.59 +bool 1.60 +TestInterruptShutdownRaceParent::RecvStartDeath() 1.61 +{ 1.62 + // this will be ordered before the OnMaybeDequeueOne event of 1.63 + // Orphan in the queue 1.64 + MessageLoop::current()->PostTask( 1.65 + FROM_HERE, 1.66 + NewRunnableMethod(this, 1.67 + &TestInterruptShutdownRaceParent::StartShuttingDown)); 1.68 + return true; 1.69 +} 1.70 + 1.71 +void 1.72 +TestInterruptShutdownRaceParent::StartShuttingDown() 1.73 +{ 1.74 + // NB: we sleep here to try and avoid receiving the Orphan message 1.75 + // while waiting for the CallExit() reply. if we fail at that, it 1.76 + // will cause the test to pass spuriously, because there won't be 1.77 + // an OnMaybeDequeueOne task for Orphan 1.78 + PR_Sleep(2000); 1.79 + 1.80 + if (CallExit()) 1.81 + fail("connection was supposed to be interrupted"); 1.82 + 1.83 + Close(); 1.84 + 1.85 + delete static_cast<TestInterruptShutdownRaceParent*>(gParentActor); 1.86 + gParentActor = nullptr; 1.87 + 1.88 + XRE_GetIOMessageLoop()->PostTask(FROM_HERE, 1.89 + NewRunnableFunction(DeleteSubprocess)); 1.90 + 1.91 + // this is ordered after the OnMaybeDequeueOne event in the queue 1.92 + MessageLoop::current()->PostTask(FROM_HERE, 1.93 + NewRunnableFunction(Done)); 1.94 + 1.95 + // |this| has been deleted, be mindful 1.96 +} 1.97 + 1.98 +bool 1.99 +TestInterruptShutdownRaceParent::RecvOrphan() 1.100 +{ 1.101 + // it would be nice to fail() here, but we'll process this message 1.102 + // while waiting for the reply CallExit(). The OnMaybeDequeueOne 1.103 + // task will still be in the queue, it just wouldn't have had any 1.104 + // work to do, if we hadn't deleted ourself 1.105 + return true; 1.106 +} 1.107 + 1.108 +//----------------------------------------------------------------------------- 1.109 +// child 1.110 + 1.111 +TestInterruptShutdownRaceChild::TestInterruptShutdownRaceChild() 1.112 +{ 1.113 + MOZ_COUNT_CTOR(TestInterruptShutdownRaceChild); 1.114 +} 1.115 + 1.116 +TestInterruptShutdownRaceChild::~TestInterruptShutdownRaceChild() 1.117 +{ 1.118 + MOZ_COUNT_DTOR(TestInterruptShutdownRaceChild); 1.119 +} 1.120 + 1.121 +bool 1.122 +TestInterruptShutdownRaceChild::RecvStart() 1.123 +{ 1.124 + if (!SendStartDeath()) 1.125 + fail("sending StartDeath"); 1.126 + 1.127 + // See comment in StartShuttingDown(): we want to send Orphan() 1.128 + // while the parent is in its PR_Sleep() 1.129 + PR_Sleep(1000); 1.130 + 1.131 + if (!SendOrphan()) 1.132 + fail("sending Orphan"); 1.133 + 1.134 + return true; 1.135 +} 1.136 + 1.137 +bool 1.138 +TestInterruptShutdownRaceChild::AnswerExit() 1.139 +{ 1.140 + _exit(0); 1.141 + NS_RUNTIMEABORT("unreached"); 1.142 + return false; 1.143 +} 1.144 + 1.145 + 1.146 +} // namespace _ipdltest 1.147 +} // namespace mozilla