ipc/ipdl/test/cxx/TestHangs.cpp

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

michael@0 1 #include "base/process_util.h"
michael@0 2
michael@0 3 #include "TestHangs.h"
michael@0 4
michael@0 5 #include "IPDLUnitTests.h" // fail etc.
michael@0 6
michael@0 7 using base::KillProcess;
michael@0 8
michael@0 9 template<>
michael@0 10 struct RunnableMethodTraits<mozilla::_ipdltest::TestHangsParent>
michael@0 11 {
michael@0 12 static void RetainCallee(mozilla::_ipdltest::TestHangsParent* obj) { }
michael@0 13 static void ReleaseCallee(mozilla::_ipdltest::TestHangsParent* obj) { }
michael@0 14 };
michael@0 15
michael@0 16 namespace mozilla {
michael@0 17 namespace _ipdltest {
michael@0 18
michael@0 19 //-----------------------------------------------------------------------------
michael@0 20 // parent
michael@0 21
michael@0 22 TestHangsParent::TestHangsParent() : mDetectedHang(false)
michael@0 23 {
michael@0 24 MOZ_COUNT_CTOR(TestHangsParent);
michael@0 25 }
michael@0 26
michael@0 27 TestHangsParent::~TestHangsParent()
michael@0 28 {
michael@0 29 MOZ_COUNT_DTOR(TestHangsParent);
michael@0 30 }
michael@0 31
michael@0 32 void
michael@0 33 TestHangsParent::Main()
michael@0 34 {
michael@0 35 // Here we try to set things up to test the following sequence of events:
michael@0 36 //
michael@0 37 // - subprocess causes an OnMaybeDequeueOne() task to be posted to
michael@0 38 // this thread
michael@0 39 //
michael@0 40 // - subprocess hangs just long enough for the hang timer to expire
michael@0 41 //
michael@0 42 // - hang-kill code in the parent starts running
michael@0 43 //
michael@0 44 // - subprocess replies to message while hang code runs
michael@0 45 //
michael@0 46 // - reply is processed in OnMaybeDequeueOne() before Close() has
michael@0 47 // been called or the channel error notification has been posted
michael@0 48
michael@0 49 // this tells the subprocess to send us Nonce()
michael@0 50 if (!SendStart())
michael@0 51 fail("sending Start");
michael@0 52
michael@0 53 // now we sleep here for a while awaiting the Nonce() message from
michael@0 54 // the child. since we're not blocked on anything, the IO thread
michael@0 55 // will enqueue an OnMaybeDequeueOne() task to process that
michael@0 56 // message
michael@0 57 //
michael@0 58 // NB: PR_Sleep is exactly what we want, only the current thread
michael@0 59 // sleeping
michael@0 60 PR_Sleep(5000);
michael@0 61
michael@0 62 // when we call into this, we'll pull the Nonce() message out of
michael@0 63 // the mPending queue, but that doesn't matter ... the
michael@0 64 // OnMaybeDequeueOne() event will remain
michael@0 65 if (CallStackFrame() && mDetectedHang)
michael@0 66 fail("should have timed out!");
michael@0 67
michael@0 68 // the Close() task in the queue will shut us down
michael@0 69 }
michael@0 70
michael@0 71 bool
michael@0 72 TestHangsParent::ShouldContinueFromReplyTimeout()
michael@0 73 {
michael@0 74 mDetectedHang = true;
michael@0 75
michael@0 76 // so we've detected a timeout after 2 ms ... now we cheat and
michael@0 77 // sleep for a long time, to allow the subprocess's reply to come
michael@0 78 // in
michael@0 79
michael@0 80 PR_Sleep(5000);
michael@0 81
michael@0 82 // reply should be here; we'll post a task to shut things down.
michael@0 83 // This must be after OnMaybeDequeueOne() in the event queue.
michael@0 84 MessageLoop::current()->PostTask(
michael@0 85 FROM_HERE, NewRunnableMethod(this, &TestHangsParent::CleanUp));
michael@0 86
michael@0 87 return false;
michael@0 88 }
michael@0 89
michael@0 90 bool
michael@0 91 TestHangsParent::AnswerStackFrame()
michael@0 92 {
michael@0 93 if (PTestHangs::HANG != state()) {
michael@0 94 if (CallStackFrame())
michael@0 95 fail("should have timed out!");
michael@0 96 }
michael@0 97 else {
michael@0 98 // minimum possible, 2 ms. We want to detecting a hang to race
michael@0 99 // with the reply coming in, as reliably as possible
michael@0 100 SetReplyTimeoutMs(2);
michael@0 101
michael@0 102 if (CallHang())
michael@0 103 fail("should have timed out!");
michael@0 104 }
michael@0 105
michael@0 106 return true;
michael@0 107 }
michael@0 108
michael@0 109 void
michael@0 110 TestHangsParent::CleanUp()
michael@0 111 {
michael@0 112 if (!KillProcess(OtherProcess(), 0, false))
michael@0 113 fail("terminating child process");
michael@0 114 Close();
michael@0 115 }
michael@0 116
michael@0 117
michael@0 118 //-----------------------------------------------------------------------------
michael@0 119 // child
michael@0 120
michael@0 121 TestHangsChild::TestHangsChild()
michael@0 122 {
michael@0 123 MOZ_COUNT_CTOR(TestHangsChild);
michael@0 124 }
michael@0 125
michael@0 126 TestHangsChild::~TestHangsChild()
michael@0 127 {
michael@0 128 MOZ_COUNT_DTOR(TestHangsChild);
michael@0 129 }
michael@0 130
michael@0 131 bool
michael@0 132 TestHangsChild::AnswerHang()
michael@0 133 {
michael@0 134 puts(" (child process is 'hanging' now)");
michael@0 135
michael@0 136 // just sleep until we're reasonably confident the 1ms hang
michael@0 137 // detector fired in the parent process and it's sleeping in
michael@0 138 // ShouldContinueFromReplyTimeout()
michael@0 139 PR_Sleep(1000);
michael@0 140
michael@0 141 return true;
michael@0 142 }
michael@0 143
michael@0 144 } // namespace _ipdltest
michael@0 145 } // namespace mozilla

mercurial