sl@0: // Copyright (c) 1998-2009 Nokia Corporation and/or its subsidiary(-ies). sl@0: // All rights reserved. sl@0: // This component and the accompanying materials are made available sl@0: // under the terms of the License "Eclipse Public License v1.0" sl@0: // which accompanies this distribution, and is available sl@0: // at the URL "http://www.eclipse.org/legal/epl-v10.html". sl@0: // sl@0: // Initial Contributors: sl@0: // Nokia Corporation - initial contribution. sl@0: // sl@0: // Contributors: sl@0: // sl@0: // Description: sl@0: // e32test\thread\t_thread2.cpp sl@0: // More tests the RThread class (T_THREAD was getting too big) sl@0: // Overview: sl@0: // Tests the RThread class sl@0: // API Information: sl@0: // RThread sl@0: // Details: sl@0: // - Test running a thread that suspends itself. This activity has sl@0: // deadlocked the Emulator in the past. sl@0: // - Test a server panicking a thread in another process that's already exited sl@0: // Platforms/Drives/Compatibility: sl@0: // All. sl@0: // Assumptions/Requirement/Pre-requisites: sl@0: // Failures and causes: sl@0: // Base Port information: sl@0: // sl@0: // sl@0: sl@0: #define __E32TEST_EXTENSION__ sl@0: #include sl@0: #include sl@0: #include sl@0: sl@0: const TInt KHeapSize=0x200; sl@0: sl@0: _LIT(KMyName, "T_THREAD2"); sl@0: sl@0: LOCAL_D RTest test(KMyName); sl@0: sl@0: LOCAL_C TInt SuspendThread(TAny*) sl@0: { sl@0: sl@0: RThread().Suspend(); sl@0: return(KErrNone); sl@0: } sl@0: sl@0: sl@0: LOCAL_D void TestSelfSuspend(TOwnerType anOwnerType) sl@0: // sl@0: // Test running a thread that suspends itself. This activity has sl@0: // deadlocked the Emulator in the past sl@0: // sl@0: { sl@0: sl@0: RThread suspendThread; sl@0: TInt r; sl@0: TRequestStatus s; sl@0: TInt jit=User::JustInTime(); sl@0: test.Start(_L("Test running a thread which suspends itself")); sl@0: test.Next(_L("Create the thread")); sl@0: r=suspendThread.Create(KNullDesC,SuspendThread,KDefaultStackSize,KHeapSize,KHeapSize,(TAny*)NULL,anOwnerType); sl@0: test(r==KErrNone); sl@0: suspendThread.Logon(s); sl@0: suspendThread.Resume(); sl@0: test.Next(_L("Wait a second")); sl@0: User::After(1000000); sl@0: User::SetJustInTime(EFalse); sl@0: suspendThread.Panic(_L("FEDCBA9876543210fedcba"),999); sl@0: User::WaitForRequest(s); sl@0: User::SetJustInTime(jit); sl@0: test(suspendThread.ExitType()==EExitPanic); sl@0: test(suspendThread.ExitReason()==999); sl@0: test(suspendThread.ExitCategory()==_L("FEDCBA9876543210")); sl@0: CLOSE_AND_WAIT(suspendThread); sl@0: test.End(); sl@0: } sl@0: sl@0: sl@0: _LIT(KServerName,"MyServer"); sl@0: sl@0: RSemaphore TheSemaphore; sl@0: sl@0: class CMySession : public CSession2 sl@0: { sl@0: public: sl@0: CMySession(); sl@0: virtual void ServiceL(const RMessage2& aMessage); sl@0: }; sl@0: sl@0: class CMyServer : public CServer2 sl@0: { sl@0: public: sl@0: CMyServer(); sl@0: virtual CSession2* NewSessionL(const TVersion& aVersion, const RMessage2& aMessage) const; sl@0: }; sl@0: sl@0: class RSession : public RSessionBase sl@0: { sl@0: public: sl@0: TInt Open(); sl@0: void Test(TRequestStatus& aStatus); sl@0: }; sl@0: sl@0: CMySession::CMySession() sl@0: { sl@0: } sl@0: sl@0: CMyServer::CMyServer() : sl@0: CServer2(0) sl@0: { sl@0: } sl@0: sl@0: CSession2* CMyServer::NewSessionL(const TVersion&, const RMessage2&) const sl@0: { sl@0: RDebug::Printf("Server: create session"); sl@0: return new (ELeave) CMySession; sl@0: } sl@0: sl@0: void CMySession::ServiceL(const RMessage2& aMessage) sl@0: { sl@0: RDebug::Printf("Server: receive message"); sl@0: TheSemaphore.Wait(); sl@0: RDebug::Printf("Server: panic client"); sl@0: aMessage.Panic(_L("!!!"), 1); sl@0: CActiveScheduler::Stop(); sl@0: } sl@0: sl@0: TInt RSession::Open() sl@0: { sl@0: return CreateSession(KServerName, TVersion()); sl@0: } sl@0: sl@0: void RSession::Test(TRequestStatus& aStatus) sl@0: { sl@0: RDebug::Printf("Client: send message"); sl@0: SendReceive(0, TIpcArgs(), aStatus); sl@0: RDebug::Printf("Client: send done"); sl@0: } sl@0: sl@0: TInt ServerThread(TAny*) sl@0: { sl@0: RDebug::Printf("Server: start"); sl@0: sl@0: CTrapCleanup* cleanup = CTrapCleanup::New(); sl@0: sl@0: CActiveScheduler* pR = new CActiveScheduler; sl@0: if (pR == NULL) sl@0: return KErrNoMemory; sl@0: CActiveScheduler::Install(pR); sl@0: sl@0: CMyServer* pS = new CMyServer; sl@0: if (pS == NULL) sl@0: return KErrNoMemory; sl@0: TInt r = pS->Start(KServerName); sl@0: if (r != KErrNone) sl@0: return r; sl@0: RThread::Rendezvous(KErrNone); sl@0: sl@0: TRAP(r, CActiveScheduler::Start()); sl@0: if (r != KErrNone) sl@0: return r; sl@0: sl@0: delete pS; sl@0: delete pR; sl@0: delete cleanup; sl@0: sl@0: RDebug::Printf("Server: exit"); sl@0: return KErrNone; sl@0: } sl@0: sl@0: TInt ClientProcess() sl@0: { sl@0: RDebug::Printf("Client: open session"); sl@0: RSession session; sl@0: session.Open(); sl@0: TRequestStatus status; sl@0: RDebug::Printf("Client: send request"); sl@0: session.Test(status); sl@0: RDebug::Printf("Client: exit"); sl@0: return KErrNone; sl@0: } sl@0: sl@0: void TestServerPanic() sl@0: { sl@0: TRequestStatus status; sl@0: sl@0: test_KErrNone(TheSemaphore.CreateLocal(0)); sl@0: sl@0: RDebug::Printf("Main: start server"); sl@0: RThread serverThread; sl@0: test_KErrNone(serverThread.Create(_L("server"), ServerThread, 4096, NULL, NULL)); sl@0: serverThread.Rendezvous(status); sl@0: serverThread.Resume(); sl@0: User::WaitForRequest(status); sl@0: test_KErrNone(status.Int()); sl@0: sl@0: RDebug::Printf("Main: start client"); sl@0: RProcess clientProcess; sl@0: test_KErrNone(clientProcess.Create(KMyName, _L("client"))); sl@0: clientProcess.Resume(); sl@0: clientProcess.Logon(status); sl@0: User::WaitForRequest(status); sl@0: test_KErrNone(clientProcess.ExitReason()); sl@0: test_Equal(EExitKill, clientProcess.ExitType()); sl@0: sl@0: RDebug::Printf("Main: kick server"); sl@0: TheSemaphore.Signal(); sl@0: sl@0: RDebug::Printf("Main: wait for server to exit"); sl@0: serverThread.Logon(status); sl@0: User::WaitForRequest(status); sl@0: test_KErrNone(serverThread.ExitReason()); sl@0: test_Equal(EExitKill, serverThread.ExitType()); sl@0: sl@0: User::After(1); sl@0: RDebug::Printf("Main: exit"); sl@0: } sl@0: sl@0: sl@0: GLDEF_C TInt E32Main() sl@0: // sl@0: // Main sl@0: // sl@0: { sl@0: sl@0: if (User::CommandLineLength()) sl@0: return ClientProcess(); sl@0: sl@0: test.Title(); sl@0: __UHEAP_MARK; sl@0: sl@0: test.Start(_L("Test threads")); sl@0: sl@0: test.Next(_L("Test a thread suspending itself")); sl@0: TestSelfSuspend(EOwnerProcess); sl@0: TestSelfSuspend(EOwnerThread); sl@0: sl@0: test.Next(_L("Test a server panicking a thread in another process that's already exited")); sl@0: TestServerPanic(); sl@0: sl@0: test.End(); sl@0: __UHEAP_MARKEND; sl@0: return(KErrNone); sl@0: }