--- /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 <e32base.h>
+
+#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<OsThreadSupervisor*>(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;
+}
+