diff -r 7fdc9a71d314 -r 8ad140f3dd41 stif/TestServer/src/Testundertaker.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/stif/TestServer/src/Testundertaker.cpp Wed Oct 13 16:17:58 2010 +0300 @@ -0,0 +1,492 @@ +/* +* Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). +* All rights reserved. +* This component and the accompanying materials are made available +* under the terms of "Eclipse Public License v1.0" +* which accompanies this distribution, and is available +* at the URL "http://www.eclipse.org/legal/epl-v10.html". +* +* Initial Contributors: +* Nokia Corporation - initial contribution. +* +* Contributors: +* +* Description: This module contains implementation of CUnderTaker +* class member functions. CUnderTaker is a class, which listens +* on Test Execution Thread death, and if that thread dies, then +* UnderTaker aborts the ongoing test execution request. +* +*/ + +// INCLUDE FILES +#include +#include +#include "TestEngineClient.h" +#include +#include +#include "TestServer.h" +#include "TestServerModuleIf.h" +#include "TestServerCommon.h" +#include "PrintQueue.h" + +// EXTERNAL DATA STRUCTURES + +// EXTERNAL FUNCTION PROTOTYPES + +// CONSTANTS + +// MACROS + +// LOCAL CONSTANTS AND MACROS + +// MODULE DATA STRUCTURES + +// LOCAL FUNCTION PROTOTYPES + +// FORWARD DECLARATIONS + +// ==================== LOCAL FUNCTIONS ======================================= + +// ================= MEMBER FUNCTIONS ========================================= + + +/* +------------------------------------------------------------------------------- + + Class: CUnderTaker + + Method: NewL + + Description: Constructs a new CUnderTaker object. + + Parameters: CTestModuleContainer* aContainer :in: "Parent" + + Return Values: CUnderTaker* New undertaker + + Errors/Exceptions: Leaves if memory allocation or ConstructL leaves. + + Status: Proposal + +------------------------------------------------------------------------------- +*/ +CUnderTaker* CUnderTaker::NewL( CTestModuleContainer* aContainer ) + { + + CUnderTaker* self = new( ELeave ) CUnderTaker(); + CleanupStack::PushL( self ); + self->ConstructL( aContainer ); + CleanupStack::Pop( self ); + return self; + + } + +/* +------------------------------------------------------------------------------- + + Class: CUnderTaker + + Method: ConstructL + + Description: Second level constructor. + + Parameters: CTestModuleContainer* aExecution :in: "Parent" + + Return Values: None + + Errors/Exceptions: Panics if aContainer is NULL + + Status: Proposal + +------------------------------------------------------------------------------- +*/ +void CUnderTaker::ConstructL( CTestModuleContainer* aContainer ) + { + + __ASSERT_ALWAYS( aContainer, + CTestServer::PanicServer( ENullTestModuleContainer ) ); + + iModuleContainer = aContainer; + + } + +/* +------------------------------------------------------------------------------- + + Class: CUnderTaker + + Method: CUnderTaker + + Description: Constructor + + Parameters: None + + Return Values: None + + Errors/Exceptions: None + + Status: Proposal + +------------------------------------------------------------------------------- +*/ +CUnderTaker::CUnderTaker() : + CActive( CActive::EPriorityHigh+1 ) + { + + // By default in asynchronous mode + iSynchronousMode = EFalse; + + } + +/* +------------------------------------------------------------------------------- + + Class: CUnderTaker + + Method: ~CUnderTaker + + Description: Destructor. + Cancels active request. + + Parameters: None + + Return Values: None + + Errors/Exceptions: None + + Status: Proposal + +------------------------------------------------------------------------------- +*/ +CUnderTaker::~CUnderTaker() + { + + Cancel(); + + } + + + + +/* +------------------------------------------------------------------------------- + + Class: CUnderTaker + + Method: StartL + + Description: Starts to monitor thread. + + Parameters: None + + Return Values: TInt Always KErrNone + + Errors/Exceptions: None + + Status: Proposal + +------------------------------------------------------------------------------- +*/ +TInt CUnderTaker::StartL() + { + + SetActive(); + iModuleContainer->iThread.Logon( iStatus ); + iCancelNeeded = ETrue; + + return KErrNone; + + } + +/* +------------------------------------------------------------------------------- + + Class: CUnderTaker + + Method: RunL + + Description: Handles thread death. + Function does: + 1 ) Stops monitoring thread + 1 ) Marks thread death + 2 ) Completes ongoing requests + 3 ) Cleans the memory + + Parameters: None + + Return Values: None + + Errors/Exceptions: None + + Status: Proposal + +------------------------------------------------------------------------------- +*/ +void CUnderTaker::RunL() + { + + // Make sure that any of the test interference thread's won't stay to run. + iModuleContainer->KillTestinterferenceThread(); + + // Make sure that any of the test measurement's process won't stay to run. + iModuleContainer->KillTestMeasurement(); + + // Get the exit category + TName exitCategory = _L( "Crash reason:" ); + exitCategory.Append( iModuleContainer->iThread.ExitCategory() ); + TInt exitReason = iModuleContainer->iThread.ExitReason(); + TFullTestResult::TCaseExecutionResult exitType = TFullTestResult::ECaseException; + if( iModuleContainer->iThread.ExitType() == EExitPanic ) + { + exitType = TFullTestResult::ECasePanic; + } + + // it is not running anymore.. + iModuleContainer->iUpAndRunning = EFalse; + + // Do not monitor anymore. + iModuleContainer->iThread.LogonCancel( iStatus ); + iCancelNeeded = EFalse; + + __TRACE( KError,( CStifLogger::ERed, _L( "Execution thread crashed, exitReason = %d" ), exitReason ) ); + __TRACE( KError,( CStifLogger::ERed, exitCategory ) ); + + if ( iSynchronousMode ) + { + + // Synchronous request was running. Complete that + // operation. + __TRACE( KVerbose,( _L( "CUnderTaker::RunL Crash during synchronous operation" ) ) ); + iModuleContainer->iErrorResult = KErrDied; + iModuleContainer->Cancel(); + iModuleContainer->iUpAndRunning = EFalse; + + // Print notification + TName operationText = _L("Test module died when calling:"); + operationText.Append( iModuleContainer->iOperationText ); + + // Print to log file + __TRACE( KError,( CStifLogger::ERed, operationText ) ); + // Print to UI + iModuleContainer->iCTestModule->ErrorPrint ( 1, operationText ); + + // Stop active scheduler. + CActiveScheduler::Stop(); + + // Execution continues from CTestModuleContainer::StartAndWaitOperation. + + } + else + {// Test case was running, + + __TRACE( KError,( _L( "Test case execution aborted" ) ) ); + __TRACE( KVerbose,( _L( "CUnderTaker::Run crash during test execution" ) ) ); + + TInt caseResult = KErrGeneral; + + // Check if case have any special panic or exception codes that are "passed" + if ( iModuleContainer->iAllowedExitReason != + CTestModuleIf::ENormal ) + { + + if ( iModuleContainer->iAllowedExitReason == + CTestModuleIf::EPanic && + exitType == TFullTestResult::ECasePanic && + iModuleContainer->iAllowedExitCode == exitReason ) + { + exitType = TFullTestResult::ECaseExecuted; + caseResult = KErrNone; + exitCategory = _L("Allowed case panic"); + + __TRACE( KError,( _L( "Test case execution panic, setting to OK" ) ) ); + } + + if ( iModuleContainer->iAllowedExitReason == + CTestModuleIf::EException && + exitType == TFullTestResult::ECaseException && + iModuleContainer->iAllowedExitCode == exitReason ) + { + exitType = TFullTestResult::ECaseExecuted; + caseResult = KErrNone; + exitCategory = _L("Allowed case exception"); + + __TRACE( KError,( _L( "Test case execution exception, setting to OK" ) ) ); + } + + + } + + // This was asynchronous request, and nobody is waiting for it + // completion in server, so all clean-up must be done here + + // Forget iTestThreadContainer pointer, memory is freed because test thread + // is destroyed + // This is needed to prevent from accessing memory from thread that is destroyed. + // Do this only if test is been executed. + iModuleContainer->iThreadContainer = NULL; + + if (iModuleContainer->iCTestExecution != NULL) + { + // Execution thread have been killed + iModuleContainer->iCTestExecution->SetThreadState( CTestExecution::ECancelled ); + + + // Cancel the request + iModuleContainer->iCTestExecution->CompleteTestExecution( KErrNone, + exitType, + exitReason, + caseResult, + exitCategory ); + + // If the print queue is empty, and there is active print + // request, then cancel that request. + // NOTE: Case queue not empty AND request waiting AND + // thread terminated can't happen due iPrintMutex + iModuleContainer->iCTestExecution->CompletePrintRequestIfQueueEmpty(); + } + else + { + __TRACE( KError,( _L( "STIF internal error - iCTestExecution is NULL in CUnderTaker::RunL." ) ) ); + User::Leave(KErrGeneral); + } + // Free the memory + // Remove undertaker from module container to make sure that + // it does not delete this. + iModuleContainer->iUnderTaker = NULL; + delete iModuleContainer; + iModuleContainer = NULL; + + // Suicide. "Parent", i.e iModuleContainer has already died + // and no-one have pointer to this active object, so die. + delete this; + + } + + } + + +/* +------------------------------------------------------------------------------- + + Class: CUnderTaker + + Method: DoCancel + + Description: Stops thread monitoring + + Parameters: None + + Return Values: None + + Errors/Exceptions: None + + Status: Proposal + +------------------------------------------------------------------------------- +*/ + +void CUnderTaker::DoCancel() + { + + if( iCancelNeeded && iModuleContainer ) + { + iModuleContainer->iThread.LogonCancel( iStatus ); + } + else + { + // Note that iModuleContainer can be NULL if iCancelNeeded is EFalse + __ASSERT_ALWAYS( iModuleContainer, + CTestServer::PanicServer( ENullTestModuleContainer ) ); + } + + } + +/* +------------------------------------------------------------------------------- + + Class: CUnderTaker + + Method: RunError + + Description: Handle errors. RunL function does not leave, so one should + never come here. + + Print trace and let framework handle error( i.e to do Panic ) + + Parameters: TInt aError: :in: Error code + + Return Values: TInt Error code + + Errors/Exceptions: None + + Status: Proposal + +------------------------------------------------------------------------------- +*/ +TInt CUnderTaker::RunError( TInt aError ) + { + __TRACE( KError,( _L( "CUnderTaker::RunError" ) ) ); + + return aError; + + } + +/* +------------------------------------------------------------------------------- + + Class: CUnderTaker + + Method: Completed + + Description: Is request completed + + Parameters: None + + Return Values: TBool Completed? + + Errors/Exceptions: None + + Status: Proposal + +------------------------------------------------------------------------------- +*/ +TBool CUnderTaker::Completed() + { + + if( iStatus == KRequestPending ) + { + return EFalse; + } + else + { + return ETrue; + } + + } + +/* +------------------------------------------------------------------------------- + + Class: CUnderTaker + + Method: SetSynchronousMode + + Description: Set or unsets local processing mode + + Parameters: const TBool aMode :in: Mode + + Return Values: None + + Errors/Exceptions: None + + Status: Proposal + +------------------------------------------------------------------------------- +*/ +void CUnderTaker::SetSynchronousMode( const TBool aMode ) + { + + iSynchronousMode = aMode; + + } + +// End of File