dbgsrv/coredumpserver/server/src/corecrashhandler.cpp
changeset 0 c6b0df440bee
equal deleted inserted replaced
-1:000000000000 0:c6b0df440bee
       
     1 // Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 //
       
    15 
       
    16 
       
    17 
       
    18 /**
       
    19  @file
       
    20  @internalTechnology
       
    21  @released
       
    22 */
       
    23 
       
    24 #include "corecrashhandler.h"
       
    25 #include "coredumpsession.h"
       
    26 
       
    27 CCrashHandler::CCrashHandler(CCoreDumpSession &aCoreSess)
       
    28     : CActive(CActive::EPriorityStandard),
       
    29     iThreadsRun(0),
       
    30     iCoreSess(aCoreSess)
       
    31 	{
       
    32 	CActiveScheduler::Add(this); 
       
    33 	}
       
    34 
       
    35 CCrashHandler* CCrashHandler::NewL(CCoreDumpSession &aCoreSess)
       
    36 {
       
    37     //LOG_MSG("->CCrashHandler::NewL()");
       
    38 	CCrashHandler* self = CCrashHandler::NewLC(aCoreSess);;
       
    39 	CleanupStack::Pop(self);
       
    40     return self;
       
    41 }
       
    42 
       
    43 CCrashHandler* CCrashHandler::NewLC(CCoreDumpSession &aCoreSess) 
       
    44 	{
       
    45     //LOG_MSG("->CCrashHandler::NewLC()");
       
    46 	CCrashHandler *self = new (ELeave) CCrashHandler(aCoreSess);;
       
    47 	CleanupStack::PushL(self);
       
    48 	self->ConstructL();
       
    49 	return self;
       
    50 	}
       
    51 
       
    52 void CCrashHandler::ConstructL()
       
    53 	{
       
    54     //LOG_MSG("->CCrashHandler::ConstructL()");
       
    55 	iCrashCount = 0;
       
    56     iRemainingEvents.ReserveL(EEventsQueueDefaultLength); 
       
    57 	}
       
    58 
       
    59 CCrashHandler::~CCrashHandler()
       
    60 	{
       
    61     //LOG_MSG("->CCrashHandler::~CCrashHandler()");
       
    62 	Cancel();
       
    63     iRemainingEvents.Reset();
       
    64     iRemainingFlashCrashEvents.Reset();
       
    65     iTids.Reset();
       
    66 	LOG_MSG("<-CCrashHandler::~CCrashHandler()");
       
    67 	}
       
    68 
       
    69 void CCrashHandler::DoCancel()
       
    70 	{
       
    71 	LOG_MSG("CCrashHandler::DoCancel()");
       
    72     iThread.LogonCancel(iStatus);
       
    73     iThread.Close();
       
    74 	}
       
    75 
       
    76 void CCrashHandler::ResetProperties(const TDesC &aProgress)
       
    77 {
       
    78     LOG_MSG("->CCrashHandler::DefaultProperties\n");
       
    79     //restore properties to default values
       
    80     TInt err = RProperty::Set(KCoreDumpServUid, ECrashProgress, aProgress);
       
    81     if(err != KErrNone)
       
    82         {
       
    83         LOG_MSG2("CCrashHandler::DefaultProperties - unable to reset 'crash progress'! err:%d\n", err);
       
    84         }
       
    85     err = RProperty::Set(KCoreDumpServUid, ECancelCrash, EFalse);  
       
    86     if(err != KErrNone)
       
    87         {
       
    88         LOG_MSG2("CCrashHandler::DefaultProperties - unable to reset 'cancel crash'! err:%d\n", err);
       
    89         }
       
    90 
       
    91     err = RProperty::Set(KCoreDumpServUid, ECrashCount, iCrashCount);  
       
    92     if(err != KErrNone)
       
    93         {
       
    94         LOG_MSG2("CCrashHandler::DefaultProperties - unable to reset 'crash count'! err:%d\n", err);
       
    95         }
       
    96 }
       
    97 
       
    98 void CCrashHandler::PostProcessL()
       
    99 {
       
   100     TInt32 action = iCoreSess.PostProcessingAction();
       
   101     LOG_MSG2("->CCrashHandler::PostProcessL - action:%d", action);
       
   102     switch(action)
       
   103         {
       
   104         case ENoPostAction:
       
   105         	{
       
   106             //no action
       
   107             break;
       
   108         	}
       
   109         case EResumeThread:
       
   110             {            
       
   111             if(iParams.iCrashInfo.iCrashSource == TCrashInfo::ELiveCrash)
       
   112             	{
       
   113 	            LOG_MSG2("CCrashHandler::PostProcessL() - resuming crashed thread:%Ld\n", iParams.iCrashInfo.iTid);
       
   114 	            iCoreSess.ResumeThreadL(iParams.iCrashInfo.iTid);
       
   115             	}
       
   116             break;
       
   117             }
       
   118 
       
   119         case EResumeProcess:
       
   120             {
       
   121             if(iParams.iCrashInfo.iCrashSource == TCrashInfo::ELiveCrash)
       
   122             	{            
       
   123 	            LOG_MSG2("CCrashHandler::PostProcessL() - resuming crashed process:%Ld\n", iParams.iCrashInfo.iPid);
       
   124 	            iCoreSess.ResumeProcessL(iParams.iCrashInfo.iPid);
       
   125             	}
       
   126             break;
       
   127             }
       
   128 
       
   129         case EKillProcess:
       
   130             {       
       
   131             if(iParams.iCrashInfo.iCrashSource == TCrashInfo::ELiveCrash)
       
   132             	{
       
   133 				LOG_MSG2("CCrashHandler::PostProcessL() - killing crashed process:%Ld\n", iParams.iCrashInfo.iPid);
       
   134 	            iCoreSess.KillProcessL(iParams.iCrashInfo.iPid);
       
   135             	}
       
   136             
       
   137             break;
       
   138             }
       
   139         case EDeleteCrashLog:
       
   140 	        {
       
   141             if(iParams.iCrashInfo.iCrashSource == TCrashInfo::ESystemCrash)
       
   142             	{	        
       
   143             	LOG_MSG2("CCrashHandler::PostProcessL() - deleting crashed process:%Ld\n", iParams.iCrashInfo.iPid);
       
   144             	}
       
   145             
       
   146             break;
       
   147 	        }
       
   148         default:
       
   149         	{
       
   150             LOG_MSG("CCrashHandler::PostProcessL() - unknown action!\n");
       
   151             User::Leave(KErrArgument);
       
   152         	}
       
   153         }
       
   154 }
       
   155 /**
       
   156  RunL() completes a previously issued ProcessCrashL call and 
       
   157  carry out user specified post processing actions. We trap the calls to 
       
   158  resume the thread, resume the process and kill the process since the thread
       
   159  or process may no longer be alive, and we would leave without finishing the
       
   160  core dump. 
       
   161  */
       
   162 void CCrashHandler::RunL()
       
   163 	{
       
   164     LOG_MSG2("->CCrashHandler::RunL(status:%d)", iStatus.Int());
       
   165 
       
   166     if(CrashInProgress())
       
   167     {
       
   168         LOG_MSG2("CCrashHandler::RunL - thread no:%d finished processing\n", iThreadsRun);
       
   169         iThread.Close();
       
   170         ResetProperties(_L("clear"));
       
   171 
       
   172         if(!(iMessage.IsNull()) && (iParams.iCrashInfo.iCrashSource == TCrashInfo::ESystemCrash) )
       
   173         	{
       
   174         	LOG_MSG("CCrashHandler::RunL - Completing the Async request After the Thread is Killed\n");
       
   175             //we have done with the processing and complete the async request
       
   176             iMessage.Complete(iStatus.Int());
       
   177         	}
       
   178 
       
   179         StartThreadL();
       
   180         return;
       
   181     }
       
   182 
       
   183     //multiple crash event case
       
   184     if(iParams.iCrashInfo.iType == TCrashInfo::ECrashException && iParams.iCrashInfo.iCrashSource == TCrashInfo::ELiveCrash)
       
   185         {
       
   186         //LOG_MSG2("CCrashHandler::RunL - marking thread:%Lu\n", iParams.iCrashInfo.iTid);
       
   187         iTids.AppendL(iParams.iCrashInfo.iTid);
       
   188         }
       
   189 
       
   190 
       
   191     PostProcessL();
       
   192     ResetProperties(_L("idle"));
       
   193 
       
   194     iCrashCount++;
       
   195       
       
   196     if(!CrashInProgress() && (iParams.iCrashInfo.iCrashSource == TCrashInfo::ESystemCrash))
       
   197     	{
       
   198     	if(!iMessage.IsNull())
       
   199     		{
       
   200         	//When there are no plugins
       
   201         	LOG_MSG("CCrashHandler::RunL - Completing the request when there are no plugins\n");
       
   202     		iMessage.Complete(iStatus.Int());
       
   203     		}
       
   204     	}
       
   205 
       
   206     if(iRemainingEvents.Count() > 0) 
       
   207         {
       
   208         ProcessCrashL(TCrashInfo::ELiveCrash);
       
   209         }
       
   210     
       
   211     if(iRemainingFlashCrashEvents.Count() > 0)
       
   212     	{
       
   213     	ProcessCrashL(TCrashInfo::ESystemCrash);
       
   214     	}
       
   215 
       
   216 	}
       
   217 
       
   218 // Report any leave to the client if possible.
       
   219 TInt CCrashHandler::RunError(TInt aError)
       
   220 	{
       
   221 	LOG_MSG2("CCrashHandler::RunError(TInt aError=%d)", aError);
       
   222     TBuf<63> errorMsg;
       
   223     errorMsg.Format(_L("Processing core dump finished abnormally! err:%d"), aError);
       
   224     User::InfoPrint(errorMsg);
       
   225     
       
   226     if(!(iMessage.IsNull()) && (iParams.iCrashInfo.iCrashSource == TCrashInfo::ESystemCrash) )
       
   227     	{
       
   228     	LOG_MSG("CCrashHandler::RunError - Completing the Async request \n");
       
   229         iMessage.Complete(aError);
       
   230     	}    
       
   231 	return KErrNone;
       
   232 	}
       
   233 
       
   234 
       
   235 void CCrashHandler::HandleCrashFromFlashL(const TCrashInfo& aCrashInf)
       
   236 	{
       
   237 	LOG_MSG("-> CCrashHandler::HandleCrashFromFlashL()");
       
   238 	
       
   239 	iRemainingFlashCrashEvents.AppendL(aCrashInf);
       
   240 	
       
   241     if(!CrashInProgress())
       
   242         {
       
   243 	    LOG_MSG("CCrashHandler::HandleCrashFromFlashL() -> ProcessCrashL\n");
       
   244         ProcessCrashL(aCrashInf.iCrashSource);
       
   245         }
       
   246 	
       
   247 	}
       
   248 
       
   249 void CCrashHandler::HandleCrashFromFlashL(const TCrashInfo& aCrashInf, const RMessage2& aMessage)
       
   250 	{
       
   251 	LOG_MSG("-> CCrashHandler::HandleCrashFromFlashL() using the async mechanism");
       
   252 	
       
   253 	if(aMessage.IsNull())
       
   254 		User::Leave(KErrArgument);
       
   255 	
       
   256 	iMessage = aMessage;
       
   257 	
       
   258 	iRemainingFlashCrashEvents.AppendL(aCrashInf);
       
   259 	
       
   260     if(!CrashInProgress())
       
   261         {
       
   262 	    LOG_MSG("CCrashHandler::HandleCrashFromFlashL() -> ProcessCrashL\n");
       
   263         ProcessCrashL(aCrashInf.iCrashSource);
       
   264         }
       
   265     else
       
   266     	{
       
   267     	LOG_MSG("CCrashHandler::HandleCrashFromFlashL() -> Crash already in progress\n");
       
   268     	}
       
   269 	
       
   270 	} 
       
   271 
       
   272 void CCrashHandler::CancelHandleCrashFromFlash(const TCrashInfo& aCrashInf)
       
   273 	{
       
   274 	LOG_MSG("-> CCrashHandler::CancelHandleCrashFromFlashL() using the async mechanism");
       
   275 	
       
   276     //if this request is pending remove the request from the queue
       
   277 	for(TInt i =0; i<iRemainingFlashCrashEvents.Count(); i++)
       
   278 		{
       
   279 		if( (iRemainingFlashCrashEvents[i].iCrashId) == (aCrashInf.iCrashId))
       
   280 			{
       
   281 			LOG_MSG("CCrashHandler::CancelHandleCrashFromFlashL() -> Removed Pending Event from the queue\n");
       
   282 			iRemainingFlashCrashEvents.Remove(i);
       
   283 			}
       
   284 		}
       
   285 	
       
   286 	}
       
   287 
       
   288 
       
   289 void CCrashHandler::HandleCrashEventL(const TCrashEventInfo &aCrashEventInfo)
       
   290     {    
       
   291     LOG_MSG3("CCrashHandler::HandleCrashEventL - type:%d, thread:%Lu\n", aCrashEventInfo.iEventType, aCrashEventInfo.iThreadId);
       
   292     //multiple crash events case
       
   293     if(aCrashEventInfo.iEventType == EEventsKillThread)
       
   294         {
       
   295         TInt index = iTids.Find(aCrashEventInfo.iThreadId);
       
   296         if(index != KErrNotFound)
       
   297             {
       
   298             LOG_MSG2("CCrashHandler::HandleCrashEventL - multiple kill event, not handling thread:%Lu\n", aCrashEventInfo.iThreadId);
       
   299             iTids.Remove(index);
       
   300 			iCoreSess.ResumeThreadL(aCrashEventInfo.iThreadId);
       
   301             return;
       
   302             }
       
   303         }
       
   304 
       
   305 
       
   306 	LOG_MSG2("CCrashHandler::HandleCrashEvent() - preprocessing action:%d\n", iCoreSess.PreProcessingAction());
       
   307     if(iCoreSess.PreProcessingAction() == ESuspendProcess)
       
   308         {
       
   309         LOG_MSG2("CCrashHandler::HandleCrashEventL - suspending crashed process:%Lu\n", aCrashEventInfo.iProcessId);
       
   310         iCoreSess.SuspendProcessL(aCrashEventInfo.iProcessId);
       
   311         }
       
   312 
       
   313     iRemainingEvents.AppendL(aCrashEventInfo); //fifo order, coping the data
       
   314 
       
   315     if(!CrashInProgress())
       
   316         {
       
   317 	    LOG_MSG("CCrashHandler::HandleCrashEvent() -> ProcessCrashL\n");
       
   318         ProcessCrashL(TCrashInfo::ELiveCrash);
       
   319         }
       
   320     }
       
   321 
       
   322 void CCrashHandler::ProcessCrashL(const TCrashInfo::TCrashSource& aType) 
       
   323 	{	
       
   324 	switch (aType)
       
   325 		{
       
   326 		case TCrashInfo::ELiveCrash :
       
   327 			{			
       
   328 			ProcessLiveCrashL();
       
   329 			break;
       
   330 			}
       
   331 		case TCrashInfo::ESystemCrash :
       
   332 			{
       
   333 			ProcessSystemCrashL();
       
   334 			break;
       
   335 			}
       
   336 		default:
       
   337 			{
       
   338 			LOG_MSG( " CCrashHandler::ProcessCrashL()  --->  ERROR: Unknown crash type" );
       
   339 			}
       
   340 		}
       
   341 	}
       
   342 
       
   343 /**
       
   344  * Handles a crash stored in the system flash
       
   345  * @leave
       
   346  */
       
   347 void CCrashHandler::ProcessSystemCrashL()
       
   348 	{
       
   349 	LOG_MSG( "->CCrashHandler::ProcessSystemCrashL()\n" );
       
   350 	//set the crash paramaters
       
   351 	iParams.iCrashInfo = iRemainingFlashCrashEvents[0];
       
   352 		
       
   353 	iRemainingFlashCrashEvents.Remove(0); //remove in fifo order				
       
   354 	
       
   355 	iCoreSess.FlashDataSource()->AnalyseCrashL(iParams.iCrashInfo.iCrashId);	
       
   356 	
       
   357 	StartThreadL();
       
   358 	}
       
   359 	
       
   360 /**
       
   361  * Handles a live crash event
       
   362  * @leave
       
   363  */
       
   364 void CCrashHandler::ProcessLiveCrashL()
       
   365 	{
       
   366     LOG_MSG( "->CCrashHandler::ProcessLiveCrashL()\n" );
       
   367 
       
   368     TCrashEventInfo &event = iRemainingEvents[0]; //serve in fifo order
       
   369 
       
   370     TCrashInfo &crashInfo = iParams.iCrashInfo;
       
   371 
       
   372 	if( !event.iThreadIdValid )
       
   373 		{
       
   374 		LOG_MSG( " ERROR *! - CCrashHandler::ProcessCrashL() - ThreadId marked as invalid\n" );
       
   375 		User::Leave( KErrCorrupt );
       
   376 		}
       
   377 
       
   378 	if( !event.iProcessIdValid )
       
   379 		{
       
   380 		LOG_MSG( " ERROR *! - CCrashHandler::ProcessCrashL() - ProcessId marked as invalid\n" );
       
   381 		User::Leave( KErrCorrupt );
       
   382 		}
       
   383 
       
   384     crashInfo.iTid = event.iThreadId;
       
   385     crashInfo.iPid = event.iProcessId;
       
   386     crashInfo.iCrashSource = TCrashInfo::ELiveCrash;
       
   387 
       
   388     if(event.iEventType == EEventsHwExc)
       
   389 		{
       
   390 		crashInfo.iType = TCrashInfo::ECrashException;
       
   391 		crashInfo.iContext = event.iThreadHwExceptionInfo.iRmdArmExcInfo; //only valid for HwExc
       
   392 		LOG_MSG2( "  crashInfo.iContext.iFaultAddress=0x%X", crashInfo.iContext.iFaultAddress );
       
   393 		LOG_MSG2( "  crashInfo.iContext.iFaultStatus=0x%X", crashInfo.iContext.iFaultStatus );
       
   394 		LOG_MSG2( "  iThreadHwExceptionInfo.iExceptionNumber=0x%X", event.iThreadHwExceptionInfo.iExceptionNumber );
       
   395 		crashInfo.iExcNumber = (TUint32)event.iThreadHwExceptionInfo.iExceptionNumber; // e32const.h :: TExcType
       
   396 		}
       
   397     else if(event.iEventType == EEventsKillThread)
       
   398 		{
       
   399 		crashInfo.iType = TCrashInfo::ECrashKill;
       
   400 		crashInfo.iReason = event.iThreadKillInfo.iExitReason; //only valid for KillThread
       
   401 		crashInfo.iExcNumber = (TUint32)event.iThreadKillInfo.iExitType; // e32const.h :: TExitType
       
   402 		TPtrC8 category( event.iThreadKillInfo.iPanicCategory, event.iThreadKillInfo.iPanicCategoryLength); //only valid for KillThread
       
   403 		crashInfo.iCategory.Copy(category);
       
   404 		}
       
   405 	else
       
   406 		{
       
   407 		LOG_MSG2( " ERROR *! - CCrashHandler::ProcessCrashL() - TEventType=%d not supported", event.iEventType );
       
   408 		User::Leave( KErrNotSupported );
       
   409 		}
       
   410     
       
   411     crashInfo.iTime = event.iEventTime.Int64();
       
   412     
       
   413     iRemainingEvents.Remove(0); //remove in fifo order
       
   414 
       
   415     StartThreadL();
       
   416     }
       
   417 
       
   418 void CCrashHandler::StartThreadL()
       
   419 {
       
   420     LOG_MSG2("->CCrashHandler::StartThreadL() iThreadsRun %d\n", iThreadsRun);
       
   421     iParams.iFormatter = iCoreSess.GetValidFormatter(iThreadsRun);      
       
   422 
       
   423     if(!iParams.iFormatter)
       
   424     	{
       
   425     	LOG_MSG("->CCrashHandler::StartThreadL() no formatters found\n");
       
   426         iThreadsRun = 0;
       
   427         RunL();
       
   428         return;
       
   429     	}
       
   430     
       
   431     //SELF v1 and DEXC v1 arent supported for system crash
       
   432 	TBuf<KMaxFileName> pluginDesc;
       
   433 	iParams.iFormatter->GetDescription(pluginDesc);
       
   434 	
       
   435 	if(iParams.iCrashInfo.iCrashSource == TCrashInfo::ESystemCrash && (pluginDesc.Compare(KSelfV1) == 0 || pluginDesc.Compare(KDexcV1) == 0))
       
   436 		{
       
   437 		User::Leave(KErrNotSupported);
       
   438 		}  
       
   439 
       
   440     if(iParams.iCrashInfo.iCrashSource == TCrashInfo::ELiveCrash)
       
   441     	{
       
   442     	iParams.iFormatter->ConfigureDataSourceL(iCoreSess.DataSource());
       
   443     	}
       
   444     else if(iParams.iCrashInfo.iCrashSource == TCrashInfo::ESystemCrash)
       
   445     	{
       
   446     	iParams.iFormatter->ConfigureDataSourceL(iCoreSess.FlashDataSource());
       
   447     	}
       
   448     else
       
   449     	{
       
   450     	//If we dont know the crash type we cant continue - programming error (dont tell user that though!)
       
   451     	__ASSERT_ALWAYS(ETrue, User::Panic(_L("Unknown crash type"), KErrUnknown));
       
   452     	}
       
   453     
       
   454 
       
   455     LOG_MSG("CCrashHandler::StartThreadL - creating the processing thread\n");
       
   456 
       
   457     TInt err = iThread.Create(KCrashProcessingThread, CCrashHandler::Processing, KDefaultStackSize, NULL, (TAny*)&iParams);
       
   458     if(err != KErrNone)
       
   459         {
       
   460         LOG_MSG2("CCrashHandler::StartThreadL - unable to create thread! err:%d\n", err);
       
   461         User::Leave(err);
       
   462         }
       
   463 
       
   464     ++iThreadsRun;
       
   465     
       
   466     iThread.Rendezvous(iStatus);    
       
   467     iThread.Resume();
       
   468     User::WaitForRequest(iStatus);
       
   469 
       
   470     User::LeaveIfError(iStatus.Int()); //something bad happened
       
   471 
       
   472     iThread.Logon(iStatus);
       
   473     //LOG_MSG("CCrashHandler::ProcessCrash() -> waiting for processing thread to finish\n");
       
   474     SetActive(); //wait for thread termination event
       
   475 }
       
   476 
       
   477 TInt CCrashHandler::Processing(TAny* aParams)
       
   478     {
       
   479     //LOG_MSG("-> CCrashHandler::CrashProcessing()");
       
   480     RThread::Rendezvous(KErrNone);
       
   481 //    __UHEAP_MARK;
       
   482 	TInt err = KErrNoMemory;
       
   483     CTrapCleanup* cleanup = CTrapCleanup::New();
       
   484 	if(cleanup)
       
   485 		{
       
   486 	    TCrashThreadParams *params = static_cast<TCrashThreadParams*>(aParams);
       
   487         LOG_MSG("CCrashHandler::CrashProcessing() -> formatter.CrashEventL");
       
   488         TRAP(err, params->iFormatter->CrashEventL(&params->iCrashInfo)); 
       
   489 		delete cleanup;
       
   490 		}
       
   491 //    __UHEAP_MARKEND;
       
   492     LOG_MSG2("CCrashHandler::CrashProcessing - processing thread returns: %d\n", err);
       
   493     return err;
       
   494     }
       
   495 
       
   496 //eof
       
   497