sl@0: // Copyright (c) 2007-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\misc\t_destruct_slave.cpp sl@0: // sl@0: // sl@0: sl@0: #define __E32TEST_EXTENSION__ sl@0: sl@0: #include sl@0: #include sl@0: #include sl@0: #include sl@0: #include sl@0: sl@0: #include "t_destruct.h" sl@0: sl@0: _LIT(KDynamicDll, "t_destruct_dll2"); sl@0: sl@0: class TTestObject sl@0: { sl@0: public: sl@0: TTestType iTestType; sl@0: public: sl@0: TTestObject(); sl@0: ~TTestObject(); sl@0: }; sl@0: sl@0: RTest test(_L("t_desruct_slave")); sl@0: TThreadId MainThreadId; sl@0: TTestObject GlobalObjectWithDestructor; sl@0: sl@0: void Panic(TInt aReason) sl@0: { sl@0: User::Panic(_L("t_destruct_slave"), aReason); sl@0: } sl@0: sl@0: TInt ExitThread(TAny*) sl@0: { sl@0: return KErrNone; sl@0: } sl@0: sl@0: TInt PanicThread(TAny*) sl@0: { sl@0: Panic(KErrNone); sl@0: return KErrNone; sl@0: } sl@0: sl@0: TInt LoopThread(TAny*) sl@0: { sl@0: // Open handle on dynamic DLL in this thread sl@0: RLibrary library; sl@0: test_KErrNone(library.Load(KDynamicDll)); sl@0: for (;;) sl@0: ; sl@0: } sl@0: sl@0: TInt ChildThread(TAny* aArg) sl@0: { sl@0: TInt testType = (TInt)aArg; sl@0: RThread mainThread; sl@0: TInt r = mainThread.Open(MainThreadId); sl@0: if (r != KErrNone) sl@0: return r; sl@0: // Open handle on dynamic DLL in this thread sl@0: RLibrary library; sl@0: test_KErrNone(library.Load(KDynamicDll)); sl@0: RThread().Rendezvous(KErrNone); sl@0: TRequestStatus status; sl@0: mainThread.Logon(status); sl@0: User::WaitForRequest(status); sl@0: if (mainThread.ExitType() != EExitKill) sl@0: return KErrGeneral; sl@0: if (mainThread.ExitReason() != KErrNone) sl@0: return mainThread.ExitReason(); sl@0: mainThread.Close(); sl@0: if (testType != ETestRecursive) sl@0: { sl@0: RMsgQueue messageQueue; sl@0: r = messageQueue.OpenGlobal(KMessageQueueName); sl@0: if (r != KErrNone) sl@0: return r; sl@0: r = messageQueue.Send(EMessagePreDestruct); sl@0: if (r != KErrNone) sl@0: return r; sl@0: } sl@0: return testType; sl@0: } sl@0: sl@0: TInt PermanentThread(TAny* aArg) sl@0: { sl@0: TInt testType = (TInt)aArg; sl@0: // Open handle on dynamic DLL in this thread sl@0: RLibrary library; sl@0: TInt r = library.Load(KDynamicDll); sl@0: if (r != KErrNone) sl@0: return r; sl@0: RMsgQueue messageQueue; sl@0: r = messageQueue.OpenGlobal(KMessageQueueName); sl@0: if (r != KErrNone) sl@0: return r; sl@0: r = messageQueue.Send(EMessagePreDestruct); sl@0: if (r != KErrNone) sl@0: return r; sl@0: messageQueue.Close(); sl@0: User::SetCritical(User::EProcessPermanent); sl@0: User::Exit(testType); sl@0: return KErrGeneral; sl@0: } sl@0: sl@0: TTestObject::TTestObject() sl@0: { sl@0: RDebug::Printf("t_destruct_slave constructor called\n"); sl@0: RMsgQueue messageQueue; sl@0: TInt r = messageQueue.OpenGlobal(KMessageQueueName); sl@0: if (r != KErrNone) sl@0: Panic(r); sl@0: messageQueue.Send(EMessageConstruct); sl@0: if (r != KErrNone) sl@0: Panic(r); sl@0: } sl@0: sl@0: TTestObject::~TTestObject() sl@0: { sl@0: RDebug::Printf("t_destruct_slave destructor called\n"); sl@0: if (iTestType == ETestRecursive) sl@0: { sl@0: // Start child thread passing this thread's id sl@0: MainThreadId = RThread().Id(); sl@0: RThread childThread; sl@0: test_KErrNone(childThread.Create(_L("ChildThread"), ChildThread, 4096, NULL, (TAny*)iTestType)); sl@0: TRequestStatus status; sl@0: childThread.Rendezvous(status); sl@0: childThread.Resume(); sl@0: sl@0: // Wait for child to open handle on this thread sl@0: User::WaitForRequest(status); sl@0: test_KErrNone(status.Int()); sl@0: childThread.Close(); sl@0: sl@0: // Set this thread non-critical sl@0: User::SetCritical(User::ENotCritical); sl@0: } sl@0: else if (iTestType == ETestDestructorExits) sl@0: { sl@0: User::Exit(iTestType); sl@0: } sl@0: sl@0: RMsgQueue messageQueue; sl@0: TInt r = messageQueue.OpenGlobal(KMessageQueueName); sl@0: if (r != KErrNone) sl@0: Panic(r); sl@0: messageQueue.Send(EMessageDestruct); sl@0: if (r != KErrNone) sl@0: Panic(r); sl@0: } sl@0: sl@0: TInt E32Main() sl@0: { sl@0: StaticMain(); sl@0: sl@0: RBuf cmd; sl@0: test_KErrNone(cmd.Create(User::CommandLineLength())); sl@0: User::CommandLine(cmd); sl@0: sl@0: TLex lex(cmd); sl@0: TTestType type; sl@0: test_KErrNone(lex.Val((TInt&)type)); sl@0: GlobalObjectWithDestructor.iTestType = type; sl@0: sl@0: RMsgQueue messageQueue; sl@0: test_KErrNone(messageQueue.OpenGlobal(KMessageQueueName)); sl@0: sl@0: // Dynamically load DLL with global data sl@0: RLibrary library; sl@0: test_KErrNone(library.Load(KDynamicDll)); sl@0: sl@0: switch(type) sl@0: { sl@0: case ETestMainThreadReturn: sl@0: test_KErrNone(messageQueue.Send(EMessagePreDestruct)); sl@0: return type; sl@0: sl@0: case ETestMainThreadExit: sl@0: test_KErrNone(messageQueue.Send(EMessagePreDestruct)); sl@0: User::Exit(type); sl@0: break; sl@0: sl@0: case ETestChildThreadReturn: sl@0: { sl@0: // Start child thread passing this thread's id sl@0: MainThreadId = RThread().Id(); sl@0: RThread childThread; sl@0: test_KErrNone(childThread.Create(_L("ChildThread"), ChildThread, 4096, NULL, (TAny*)type)); sl@0: TRequestStatus status; sl@0: childThread.Rendezvous(status); sl@0: childThread.Resume(); sl@0: sl@0: User::After(1); sl@0: sl@0: // Wait for child to open handle on this thread sl@0: User::WaitForRequest(status); sl@0: test_KErrNone(status.Int()); sl@0: childThread.Close(); sl@0: sl@0: // Set this thread non-critical and exit sl@0: User::SetCritical(User::ENotCritical); sl@0: } sl@0: break; sl@0: sl@0: case ETestOtherThreadExit: sl@0: { sl@0: RThread childThread; sl@0: test_KErrNone(childThread.Create(_L("ChildThread"), ExitThread, 4096, NULL, (TAny*)type)); sl@0: childThread.Resume(); sl@0: TRequestStatus status; sl@0: childThread.Logon(status); sl@0: User::WaitForRequest(status); sl@0: test_KErrNone(status.Int()); sl@0: childThread.Close(); sl@0: test_KErrNone(messageQueue.Send(EMessagePreDestruct)); sl@0: } sl@0: return type; sl@0: sl@0: case ETestOtherThreadPanic: sl@0: { sl@0: RThread childThread; sl@0: test_KErrNone(childThread.Create(_L("ChildThread"), PanicThread, 4096, NULL, (TAny*)type)); sl@0: childThread.Resume(); sl@0: TRequestStatus status; sl@0: childThread.Logon(status); sl@0: User::WaitForRequest(status); sl@0: test_KErrNone(status.Int()); sl@0: childThread.Close(); sl@0: test_KErrNone(messageQueue.Send(EMessagePreDestruct)); sl@0: } sl@0: return type; sl@0: sl@0: case ETestOtherThreadRunning: sl@0: { sl@0: RThread childThread; sl@0: test_KErrNone(childThread.Create(_L("ChildThread"), LoopThread, 4096, NULL, (TAny*)type)); sl@0: childThread.Resume(); sl@0: childThread.Close(); sl@0: test_KErrNone(messageQueue.Send(EMessagePreDestruct)); sl@0: } sl@0: return type; sl@0: sl@0: case ETestPermanentThreadExit: sl@0: { sl@0: RThread childThread; sl@0: test_KErrNone(childThread.Create(_L("ChildThread"), PermanentThread, 4096, NULL, (TAny*)type)); sl@0: childThread.Resume(); sl@0: TRequestStatus status; sl@0: childThread.Logon(status); sl@0: User::WaitForRequest(status); sl@0: test_KErrNone(status.Int()); sl@0: childThread.Close(); sl@0: } sl@0: break; sl@0: sl@0: case ETestRecursive: sl@0: test_KErrNone(messageQueue.Send(EMessagePreDestruct)); sl@0: break; sl@0: sl@0: case ETestDestructorExits: sl@0: test_KErrNone(messageQueue.Send(EMessagePreDestruct)); sl@0: break; sl@0: sl@0: case ETestLastThreadPanic: sl@0: test_KErrNone(messageQueue.Send(EMessagePreDestruct)); sl@0: Panic(type); sl@0: break; sl@0: sl@0: default: sl@0: test(EFalse); sl@0: } sl@0: return KErrNone; sl@0: }