ipc/ipdl/test/cxx/TestHangs.cpp

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

mercurial