diff -r f5050f1da672 -r 04becd199f91 javaruntimes/starterutils/src.s60/osthreadsupervisor.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/javaruntimes/starterutils/src.s60/osthreadsupervisor.cpp Tue Apr 27 16:30:29 2010 +0300 @@ -0,0 +1,158 @@ +/* +* 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 class is for thread death monitoring. +* +*/ + +#include + +#include "osthreadsupervisor.h" + +#include "runtimeexception.h" + +#include "logger.h" +#include "javacommonutils.h" + +using namespace java::runtime; +using namespace java::util; + + +OsThreadSupervisor::OsThreadSupervisor(bool tryThreadDumping) : + mDoExit(false), mTryThreadDump(tryThreadDumping) +{ + JELOG2(EJavaRuntime); + startUndertakerThread(); +} + +OsThreadSupervisor::~OsThreadSupervisor() +{ + JELOG2(EJavaRuntime); + // Wake the undertaker thread in order to close it. + mDoExit = true; + mRequestStatus = KRequestPending; + TRequestStatus* requestStatus = &mRequestStatus; + mSupervisorThread.RequestComplete(requestStatus, KErrNone); + mSupervisorThread.Close(); +} + + +void OsThreadSupervisor::startUndertakerThread() +{ + JELOG2(EJavaRuntime); + RThread thread; + + // Create the undertaker thread. + _LIT(KUndertakerName, "JavaMidp undertaker"); + TInt err = thread.Create(KUndertakerName, + OsThreadSupervisor::underTakerThreadMain, + 0x2000, 0, this); + + if (err == KErrNone) + { + // Set the prioroty to high. + thread.SetPriority(EPriorityMuchMore); + thread.Resume(); + thread.Close(); + } + else + { + thread.Close(); + std::string errorStr("Not able to create undertaker thread. Reason: "); + errorStr.append(JavaCommonUtils::intToString(err)); + throw RuntimeException(errorStr, __FILE__, __FUNCTION__, __LINE__); + } + +} + +int OsThreadSupervisor::underTakerThreadMain(void* starter) +{ + JELOG2(EJavaRuntime); + OsThreadSupervisor* supervisor = + reinterpret_cast(starter); + + // Open the thread handle so that RequstComplete methods can be + // called from another thread. + supervisor->mSupervisorThread.Open(RThread().Id()); + + RUndertaker underTaker; + if (underTaker.Create() == KErrNone) + { + // Get the process id of this process. + TProcessId processId = RProcess().Id(); + int status = KErrNone; + LOG1(EJavaRuntime, EInfo, "Starting to monitor MIDP process %lld", + processId.Id()); + // We will receive notification from ALL the thread deaths from all + // processes. That is why the looping is needed. + while (status == KErrNone) + { + int threadHandle; + + // Logon to monitor thread deaths. + status = underTaker.Logon(supervisor->mRequestStatus, threadHandle); + if (status != KErrNone) + { + ELOG1(EJavaRuntime, "Undertaker thread failed to do logon. " + " Reason: %d", status); + break; + } + + // Start to wait thread deaths or shutdown indication. + User::WaitForRequest(supervisor->mRequestStatus); + if (supervisor->mDoExit) + { + // We are going down, so no need to monitor thread deaths. + // Closing the undertaker thread. + LOG(EJavaRuntime, EInfo, "Undertaker closed succesfully"); + return 0; + } + RThread thread; + thread.SetHandle(threadHandle); + LOG2(EJavaRuntime, EInfo, "A thread %lld has died with exit type %d", + thread.Id().Id(), thread.ExitType()); + + // We are only interested in panicing threads. + if (thread.ExitType() == EExitPanic) + { + RProcess terminatedProcess; + status = thread.Process(terminatedProcess); + if (status == KErrNone) + { + LOG2(EJavaRuntime, EInfo, + "Thread panic from process id: %lld. " + "Our id is: %lld", + terminatedProcess.Id().Id(), processId.Id()); + // Check if this thread belong to our process. + if (terminatedProcess.Id() == processId) + { + // One of MIDP threads has paniced, so lets terminate + // the whole process. + status = KErrDied; + } + terminatedProcess.Close(); + } + else + { + ELOG1(EJavaRuntime, "Solving paniced thread's process " + "failed. Reason: %d", status); + } + } + thread.Close(); + } + } + ELOG(EJavaRuntime, "Panic in one of the MIDP threads. Stopping process!"); + RProcess().Terminate(KErrAbort); + return 0; +} +