|
1 // Copyright (c) 1998-2009 Nokia Corporation and/or its subsidiary(-ies). |
|
2 // All rights reserved. |
|
3 // This component and the accompanying materials are made available |
|
4 // under the terms of the License "Eclipse Public License v1.0" |
|
5 // which accompanies this distribution, and is available |
|
6 // at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
7 // |
|
8 // Initial Contributors: |
|
9 // Nokia Corporation - initial contribution. |
|
10 // |
|
11 // Contributors: |
|
12 // |
|
13 // Description: |
|
14 // e32test\thread\t_thread2.cpp |
|
15 // More tests the RThread class (T_THREAD was getting too big) |
|
16 // Overview: |
|
17 // Tests the RThread class |
|
18 // API Information: |
|
19 // RThread |
|
20 // Details: |
|
21 // - Test running a thread that suspends itself. This activity has |
|
22 // deadlocked the Emulator in the past. |
|
23 // - Test a server panicking a thread in another process that's already exited |
|
24 // Platforms/Drives/Compatibility: |
|
25 // All. |
|
26 // Assumptions/Requirement/Pre-requisites: |
|
27 // Failures and causes: |
|
28 // Base Port information: |
|
29 // |
|
30 // |
|
31 |
|
32 #define __E32TEST_EXTENSION__ |
|
33 #include <e32test.h> |
|
34 #include <e32panic.h> |
|
35 #include <e32debug.h> |
|
36 |
|
37 const TInt KHeapSize=0x200; |
|
38 |
|
39 _LIT(KMyName, "T_THREAD2"); |
|
40 |
|
41 LOCAL_D RTest test(KMyName); |
|
42 |
|
43 LOCAL_C TInt SuspendThread(TAny*) |
|
44 { |
|
45 |
|
46 RThread().Suspend(); |
|
47 return(KErrNone); |
|
48 } |
|
49 |
|
50 |
|
51 LOCAL_D void TestSelfSuspend(TOwnerType anOwnerType) |
|
52 // |
|
53 // Test running a thread that suspends itself. This activity has |
|
54 // deadlocked the Emulator in the past |
|
55 // |
|
56 { |
|
57 |
|
58 RThread suspendThread; |
|
59 TInt r; |
|
60 TRequestStatus s; |
|
61 TInt jit=User::JustInTime(); |
|
62 test.Start(_L("Test running a thread which suspends itself")); |
|
63 test.Next(_L("Create the thread")); |
|
64 r=suspendThread.Create(KNullDesC,SuspendThread,KDefaultStackSize,KHeapSize,KHeapSize,(TAny*)NULL,anOwnerType); |
|
65 test(r==KErrNone); |
|
66 suspendThread.Logon(s); |
|
67 suspendThread.Resume(); |
|
68 test.Next(_L("Wait a second")); |
|
69 User::After(1000000); |
|
70 User::SetJustInTime(EFalse); |
|
71 suspendThread.Panic(_L("FEDCBA9876543210fedcba"),999); |
|
72 User::WaitForRequest(s); |
|
73 User::SetJustInTime(jit); |
|
74 test(suspendThread.ExitType()==EExitPanic); |
|
75 test(suspendThread.ExitReason()==999); |
|
76 test(suspendThread.ExitCategory()==_L("FEDCBA9876543210")); |
|
77 CLOSE_AND_WAIT(suspendThread); |
|
78 test.End(); |
|
79 } |
|
80 |
|
81 |
|
82 _LIT(KServerName,"MyServer"); |
|
83 |
|
84 RSemaphore TheSemaphore; |
|
85 |
|
86 class CMySession : public CSession2 |
|
87 { |
|
88 public: |
|
89 CMySession(); |
|
90 virtual void ServiceL(const RMessage2& aMessage); |
|
91 }; |
|
92 |
|
93 class CMyServer : public CServer2 |
|
94 { |
|
95 public: |
|
96 CMyServer(); |
|
97 virtual CSession2* NewSessionL(const TVersion& aVersion, const RMessage2& aMessage) const; |
|
98 }; |
|
99 |
|
100 class RSession : public RSessionBase |
|
101 { |
|
102 public: |
|
103 TInt Open(); |
|
104 void Test(TRequestStatus& aStatus); |
|
105 }; |
|
106 |
|
107 CMySession::CMySession() |
|
108 { |
|
109 } |
|
110 |
|
111 CMyServer::CMyServer() : |
|
112 CServer2(0) |
|
113 { |
|
114 } |
|
115 |
|
116 CSession2* CMyServer::NewSessionL(const TVersion&, const RMessage2&) const |
|
117 { |
|
118 RDebug::Printf("Server: create session"); |
|
119 return new (ELeave) CMySession; |
|
120 } |
|
121 |
|
122 void CMySession::ServiceL(const RMessage2& aMessage) |
|
123 { |
|
124 RDebug::Printf("Server: receive message"); |
|
125 TheSemaphore.Wait(); |
|
126 RDebug::Printf("Server: panic client"); |
|
127 aMessage.Panic(_L("!!!"), 1); |
|
128 CActiveScheduler::Stop(); |
|
129 } |
|
130 |
|
131 TInt RSession::Open() |
|
132 { |
|
133 return CreateSession(KServerName, TVersion()); |
|
134 } |
|
135 |
|
136 void RSession::Test(TRequestStatus& aStatus) |
|
137 { |
|
138 RDebug::Printf("Client: send message"); |
|
139 SendReceive(0, TIpcArgs(), aStatus); |
|
140 RDebug::Printf("Client: send done"); |
|
141 } |
|
142 |
|
143 TInt ServerThread(TAny*) |
|
144 { |
|
145 RDebug::Printf("Server: start"); |
|
146 |
|
147 CTrapCleanup* cleanup = CTrapCleanup::New(); |
|
148 |
|
149 CActiveScheduler* pR = new CActiveScheduler; |
|
150 if (pR == NULL) |
|
151 return KErrNoMemory; |
|
152 CActiveScheduler::Install(pR); |
|
153 |
|
154 CMyServer* pS = new CMyServer; |
|
155 if (pS == NULL) |
|
156 return KErrNoMemory; |
|
157 TInt r = pS->Start(KServerName); |
|
158 if (r != KErrNone) |
|
159 return r; |
|
160 RThread::Rendezvous(KErrNone); |
|
161 |
|
162 TRAP(r, CActiveScheduler::Start()); |
|
163 if (r != KErrNone) |
|
164 return r; |
|
165 |
|
166 delete pS; |
|
167 delete pR; |
|
168 delete cleanup; |
|
169 |
|
170 RDebug::Printf("Server: exit"); |
|
171 return KErrNone; |
|
172 } |
|
173 |
|
174 TInt ClientProcess() |
|
175 { |
|
176 RDebug::Printf("Client: open session"); |
|
177 RSession session; |
|
178 session.Open(); |
|
179 TRequestStatus status; |
|
180 RDebug::Printf("Client: send request"); |
|
181 session.Test(status); |
|
182 RDebug::Printf("Client: exit"); |
|
183 return KErrNone; |
|
184 } |
|
185 |
|
186 void TestServerPanic() |
|
187 { |
|
188 TRequestStatus status; |
|
189 |
|
190 test_KErrNone(TheSemaphore.CreateLocal(0)); |
|
191 |
|
192 RDebug::Printf("Main: start server"); |
|
193 RThread serverThread; |
|
194 test_KErrNone(serverThread.Create(_L("server"), ServerThread, 4096, NULL, NULL)); |
|
195 serverThread.Rendezvous(status); |
|
196 serverThread.Resume(); |
|
197 User::WaitForRequest(status); |
|
198 test_KErrNone(status.Int()); |
|
199 |
|
200 RDebug::Printf("Main: start client"); |
|
201 RProcess clientProcess; |
|
202 test_KErrNone(clientProcess.Create(KMyName, _L("client"))); |
|
203 clientProcess.Resume(); |
|
204 clientProcess.Logon(status); |
|
205 User::WaitForRequest(status); |
|
206 test_KErrNone(clientProcess.ExitReason()); |
|
207 test_Equal(EExitKill, clientProcess.ExitType()); |
|
208 |
|
209 RDebug::Printf("Main: kick server"); |
|
210 TheSemaphore.Signal(); |
|
211 |
|
212 RDebug::Printf("Main: wait for server to exit"); |
|
213 serverThread.Logon(status); |
|
214 User::WaitForRequest(status); |
|
215 test_KErrNone(serverThread.ExitReason()); |
|
216 test_Equal(EExitKill, serverThread.ExitType()); |
|
217 |
|
218 User::After(1); |
|
219 RDebug::Printf("Main: exit"); |
|
220 } |
|
221 |
|
222 |
|
223 GLDEF_C TInt E32Main() |
|
224 // |
|
225 // Main |
|
226 // |
|
227 { |
|
228 |
|
229 if (User::CommandLineLength()) |
|
230 return ClientProcess(); |
|
231 |
|
232 test.Title(); |
|
233 __UHEAP_MARK; |
|
234 |
|
235 test.Start(_L("Test threads")); |
|
236 |
|
237 test.Next(_L("Test a thread suspending itself")); |
|
238 TestSelfSuspend(EOwnerProcess); |
|
239 TestSelfSuspend(EOwnerThread); |
|
240 |
|
241 test.Next(_L("Test a server panicking a thread in another process that's already exited")); |
|
242 TestServerPanic(); |
|
243 |
|
244 test.End(); |
|
245 __UHEAP_MARKEND; |
|
246 return(KErrNone); |
|
247 } |