1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/ipc/ipdl/test/cxx/TestHangs.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,145 @@ 1.4 +#include "base/process_util.h" 1.5 + 1.6 +#include "TestHangs.h" 1.7 + 1.8 +#include "IPDLUnitTests.h" // fail etc. 1.9 + 1.10 +using base::KillProcess; 1.11 + 1.12 +template<> 1.13 +struct RunnableMethodTraits<mozilla::_ipdltest::TestHangsParent> 1.14 +{ 1.15 + static void RetainCallee(mozilla::_ipdltest::TestHangsParent* obj) { } 1.16 + static void ReleaseCallee(mozilla::_ipdltest::TestHangsParent* obj) { } 1.17 +}; 1.18 + 1.19 +namespace mozilla { 1.20 +namespace _ipdltest { 1.21 + 1.22 +//----------------------------------------------------------------------------- 1.23 +// parent 1.24 + 1.25 +TestHangsParent::TestHangsParent() : mDetectedHang(false) 1.26 +{ 1.27 + MOZ_COUNT_CTOR(TestHangsParent); 1.28 +} 1.29 + 1.30 +TestHangsParent::~TestHangsParent() 1.31 +{ 1.32 + MOZ_COUNT_DTOR(TestHangsParent); 1.33 +} 1.34 + 1.35 +void 1.36 +TestHangsParent::Main() 1.37 +{ 1.38 + // Here we try to set things up to test the following sequence of events: 1.39 + // 1.40 + // - subprocess causes an OnMaybeDequeueOne() task to be posted to 1.41 + // this thread 1.42 + // 1.43 + // - subprocess hangs just long enough for the hang timer to expire 1.44 + // 1.45 + // - hang-kill code in the parent starts running 1.46 + // 1.47 + // - subprocess replies to message while hang code runs 1.48 + // 1.49 + // - reply is processed in OnMaybeDequeueOne() before Close() has 1.50 + // been called or the channel error notification has been posted 1.51 + 1.52 + // this tells the subprocess to send us Nonce() 1.53 + if (!SendStart()) 1.54 + fail("sending Start"); 1.55 + 1.56 + // now we sleep here for a while awaiting the Nonce() message from 1.57 + // the child. since we're not blocked on anything, the IO thread 1.58 + // will enqueue an OnMaybeDequeueOne() task to process that 1.59 + // message 1.60 + // 1.61 + // NB: PR_Sleep is exactly what we want, only the current thread 1.62 + // sleeping 1.63 + PR_Sleep(5000); 1.64 + 1.65 + // when we call into this, we'll pull the Nonce() message out of 1.66 + // the mPending queue, but that doesn't matter ... the 1.67 + // OnMaybeDequeueOne() event will remain 1.68 + if (CallStackFrame() && mDetectedHang) 1.69 + fail("should have timed out!"); 1.70 + 1.71 + // the Close() task in the queue will shut us down 1.72 +} 1.73 + 1.74 +bool 1.75 +TestHangsParent::ShouldContinueFromReplyTimeout() 1.76 +{ 1.77 + mDetectedHang = true; 1.78 + 1.79 + // so we've detected a timeout after 2 ms ... now we cheat and 1.80 + // sleep for a long time, to allow the subprocess's reply to come 1.81 + // in 1.82 + 1.83 + PR_Sleep(5000); 1.84 + 1.85 + // reply should be here; we'll post a task to shut things down. 1.86 + // This must be after OnMaybeDequeueOne() in the event queue. 1.87 + MessageLoop::current()->PostTask( 1.88 + FROM_HERE, NewRunnableMethod(this, &TestHangsParent::CleanUp)); 1.89 + 1.90 + return false; 1.91 +} 1.92 + 1.93 +bool 1.94 +TestHangsParent::AnswerStackFrame() 1.95 +{ 1.96 + if (PTestHangs::HANG != state()) { 1.97 + if (CallStackFrame()) 1.98 + fail("should have timed out!"); 1.99 + } 1.100 + else { 1.101 + // minimum possible, 2 ms. We want to detecting a hang to race 1.102 + // with the reply coming in, as reliably as possible 1.103 + SetReplyTimeoutMs(2); 1.104 + 1.105 + if (CallHang()) 1.106 + fail("should have timed out!"); 1.107 + } 1.108 + 1.109 + return true; 1.110 +} 1.111 + 1.112 +void 1.113 +TestHangsParent::CleanUp() 1.114 +{ 1.115 + if (!KillProcess(OtherProcess(), 0, false)) 1.116 + fail("terminating child process"); 1.117 + Close(); 1.118 +} 1.119 + 1.120 + 1.121 +//----------------------------------------------------------------------------- 1.122 +// child 1.123 + 1.124 +TestHangsChild::TestHangsChild() 1.125 +{ 1.126 + MOZ_COUNT_CTOR(TestHangsChild); 1.127 +} 1.128 + 1.129 +TestHangsChild::~TestHangsChild() 1.130 +{ 1.131 + MOZ_COUNT_DTOR(TestHangsChild); 1.132 +} 1.133 + 1.134 +bool 1.135 +TestHangsChild::AnswerHang() 1.136 +{ 1.137 + puts(" (child process is 'hanging' now)"); 1.138 + 1.139 + // just sleep until we're reasonably confident the 1ms hang 1.140 + // detector fired in the parent process and it's sleeping in 1.141 + // ShouldContinueFromReplyTimeout() 1.142 + PR_Sleep(1000); 1.143 + 1.144 + return true; 1.145 +} 1.146 + 1.147 +} // namespace _ipdltest 1.148 +} // namespace mozilla