diff options
Diffstat (limited to 'src/vm/appdomain.cpp')
-rw-r--r-- | src/vm/appdomain.cpp | 290 |
1 files changed, 0 insertions, 290 deletions
diff --git a/src/vm/appdomain.cpp b/src/vm/appdomain.cpp index 563de46075..6aff6ab60a 100644 --- a/src/vm/appdomain.cpp +++ b/src/vm/appdomain.cpp @@ -95,8 +95,6 @@ static const WCHAR OTHER_DOMAIN_FRIENDLY_NAME_PREFIX[] = W("Domain"); #define STATIC_OBJECT_TABLE_BUCKET_SIZE 1020 -//#define _DEBUG_ADUNLOAD 1 - // Statics SPTR_IMPL(AppDomain, AppDomain, m_pTheAppDomain); @@ -6634,225 +6632,12 @@ void AppDomain::ExceptionUnwind(Frame *pFrame) CONTRACTL_END; LOG((LF_APPDOMAIN, LL_INFO10, "AppDomain::ExceptionUnwind for %8.8x\n", pFrame)); -#if _DEBUG_ADUNLOAD - printf("%x AppDomain::ExceptionUnwind for %8.8p\n", GetThread()->GetThreadId(), pFrame); -#endif Thread *pThread = GetThread(); _ASSERTE(pThread); LOG((LF_APPDOMAIN, LL_INFO10, "AppDomain::ExceptionUnwind: not first transition or abort\n")); } -BOOL AppDomain::StopEEAndUnwindThreads(unsigned int retryCount, BOOL *pFMarkUnloadRequestThread) -{ - CONTRACTL - { - THROWS; - GC_TRIGGERS; - MODE_ANY; - } - CONTRACTL_END; - - Thread *pThread = NULL; - DWORD nThreadsNeedMoreWork=0; - if (retryCount != (unsigned int)-1 && retryCount < g_pConfig->AppDomainUnloadRetryCount()) - { - Thread *pCurThread = GetThread(); - if (pCurThread->CatchAtSafePoint()) - pCurThread->PulseGCMode(); - - m_dwThreadsStillInAppDomain=nThreadsNeedMoreWork; - return !nThreadsNeedMoreWork; - } - - // For now piggyback on the GC's suspend EE mechanism - ThreadSuspend::SuspendEE(ThreadSuspend::SUSPEND_FOR_APPDOMAIN_SHUTDOWN); -#ifdef _DEBUG - // <TODO>@todo: what to do with any threads that didn't stop?</TODO> - _ASSERTE(ThreadStore::s_pThreadStore->DbgBackgroundThreadCount() > 0); -#endif // _DEBUG - - int totalADCount = 0; - int finalizerADCount = 0; - pThread = NULL; - - RuntimeExceptionKind reKind = kLastException; - UINT resId = 0; - SmallStackSString ssThreadId; - - while ((pThread = ThreadStore::GetThreadList(pThread)) != NULL) - { - // we already checked that we're not running in the unload domain - if (pThread == GetThread()) - { - continue; - } - -#ifdef _DEBUG - void PrintStackTraceWithADToLog(Thread *pThread); - if (LoggingOn(LF_APPDOMAIN, LL_INFO100)) { - LOG((LF_APPDOMAIN, LL_INFO100, "\nStackTrace for %x\n", pThread->GetThreadId())); - PrintStackTraceWithADToLog(pThread); - } -#endif // _DEBUG - int count = 0; - Frame *pFrame = pThread->GetFirstTransitionInto(this, &count); - if (! pFrame) { - _ASSERTE(count == 0); - continue; - } - - if (pThread != FinalizerThread::GetFinalizerThread()) - { - totalADCount += count; - nThreadsNeedMoreWork++; - } - else - { - finalizerADCount = count; - } - - // don't setup the exception info for the unloading thread unless it's the last one in - if (retryCount != ((unsigned int) -1) && retryCount > g_pConfig->AppDomainUnloadRetryCount() && reKind == kLastException) - { -#ifdef AD_BREAK_ON_CANNOT_UNLOAD - static int breakOnCannotUnload = CLRConfig::GetConfigValue(CLRConfig::INTERNAL_ADBreakOnCannotUnload); - if (breakOnCannotUnload) - _ASSERTE(!"Cannot unload AD"); -#endif // AD_BREAK_ON_CANNOT_UNLOAD - reKind = kCannotUnloadAppDomainException; - resId = IDS_EE_ADUNLOAD_CANT_UNWIND_THREAD; - ssThreadId.Printf(W("%x"), pThread->GetThreadId()); - STRESS_LOG2(LF_APPDOMAIN, LL_INFO10, "AppDomain::UnwindThreads cannot stop thread %x with %d transitions\n", pThread->GetThreadId(), count); - // don't break out of this early or the assert totalADCount == (int)m_dwThreadEnterCount below will fire - // it's better to chew a little extra time here and make sure our counts are consistent - } - // only abort the thread requesting the unload if it's the last one in, that way it will get - // notification that the unload failed for some other thread not being aborted. And don't abort - // the finalizer thread - let it finish it's work as it's allowed to be in there. If it won't finish, - // then we will eventually get a CannotUnloadException on it. - - if (pThread != FinalizerThread::GetFinalizerThread()) - { - - STRESS_LOG2(LF_APPDOMAIN, LL_INFO100, "AppDomain::UnwindThreads stopping %x with %d transitions\n", pThread->GetThreadId(), count); - LOG((LF_APPDOMAIN, LL_INFO100, "AppDomain::UnwindThreads stopping %x with %d transitions\n", pThread->GetThreadId(), count)); -#if _DEBUG_ADUNLOAD - printf("AppDomain::UnwindThreads %x stopping %x with first frame %8.8p\n", GetThread()->GetThreadId(), pThread->GetThreadId(), pFrame); -#endif - pThread->SetAbortRequest(EEPolicy::TA_Safe); - } - TESTHOOKCALL(UnwindingThreads(GetId().m_dwId)) ; - } - _ASSERTE(totalADCount + finalizerADCount == (int)m_dwThreadEnterCount); - - //@TODO: This is intended to catch a stress bug. Remove when no longer needed. - if (totalADCount + finalizerADCount != (int)m_dwThreadEnterCount) - FreeBuildDebugBreak(); - - // if our count did get messed up, set it to whatever count we actually found in the domain to avoid looping - // or other problems related to incorrect count. This is very much a bug if this happens - a thread should always - // exit the domain gracefully. - // m_dwThreadEnterCount = totalADCount; - - // CommonTripThread will handle the abort for any threads that we've marked - ThreadSuspend::RestartEE(FALSE, TRUE); - if (reKind != kLastException) - COMPlusThrow(reKind, resId, ssThreadId.GetUnicode()); - - _ASSERTE((totalADCount==0 && nThreadsNeedMoreWork==0) ||(totalADCount!=0 && nThreadsNeedMoreWork!=0)); - - m_dwThreadsStillInAppDomain=nThreadsNeedMoreWork; - return (totalADCount == 0); -} - -void AppDomain::UnwindThreads() -{ - // This function should guarantee appdomain - // consistency even if it fails. Everything that is going - // to make the appdomain impossible to reenter - // should be factored out - - // <TODO>@todo: need real synchronization here!!!</TODO> - CONTRACTL - { - MODE_COOPERATIVE; - THROWS; - GC_TRIGGERS; - } - CONTRACTL_END; - - int retryCount = -1; - m_dwThreadsStillInAppDomain=(ULONG)-1; - ULONGLONG startTime = CLRGetTickCount64(); - - // Force threads to go through slow path during AD unload. - TSSuspendHolder shTrap; - - BOOL fMarkUnloadRequestThread = TRUE; - - // now wait for all the threads running in our AD to get out - do - { - DWORD timeout = GetEEPolicy()->GetTimeout(OPR_AppDomainUnload); - EPolicyAction action = GetEEPolicy()->GetActionOnTimeout(OPR_AppDomainUnload, NULL); - if (timeout != INFINITE && action >= eExitProcess) { - // Escalation policy specified. - ULONGLONG curTime = CLRGetTickCount64(); - ULONGLONG elapseTime = curTime - startTime; - if (elapseTime > timeout) - { - // Escalate - switch (action) - { - case eExitProcess: - case eFastExitProcess: - case eRudeExitProcess: - case eDisableRuntime: - GetEEPolicy()->NotifyHostOnTimeout(OPR_AppDomainUnload, action); - EEPolicy::HandleExitProcessFromEscalation(action, HOST_E_EXITPROCESS_TIMEOUT); - _ASSERTE (!"Should not reach here"); - break; - default: - break; - } - } - } -#ifdef _DEBUG - if (LoggingOn(LF_APPDOMAIN, LL_INFO100)) - DumpADThreadTrack(); -#endif // _DEBUG - if (StopEEAndUnwindThreads(retryCount, &fMarkUnloadRequestThread)) - break; - if (timeout != INFINITE) - { - // Turn off the timeout used by AD. - retryCount = 1; - } - else - { - // GCStress takes a long time to unwind, due to expensive creation of - // a threadabort exception. - if (!GCStress<cfg_any>::IsEnabled()) - ++retryCount; - LOG((LF_APPDOMAIN, LL_INFO10, "AppDomain::UnwindThreads iteration %d waiting on thread count %d\n", retryCount, m_dwThreadEnterCount)); -#if _DEBUG_ADUNLOAD - printf("AppDomain::UnwindThreads iteration %d waiting on thread count %d\n", retryCount, m_dwThreadEnterCount); -#endif - } - - if (m_dwThreadEnterCount != 0) - { -#ifdef _DEBUG - GetThread()->UserSleep(20); -#else // !_DEBUG - GetThread()->UserSleep(10); -#endif // !_DEBUG - } - } - while (TRUE) ; -} - #ifdef _DEBUG void AppDomain::TrackADThreadEnter(Thread *pThread, Frame *pFrame) @@ -7506,81 +7291,6 @@ ULONGLONG g_ObjFinalizeStartTime = 0; Volatile<BOOL> g_FinalizerIsRunning = FALSE; Volatile<ULONG> g_FinalizerLoopCount = 0; -ULONGLONG GetObjFinalizeStartTime() -{ - LIMITED_METHOD_CONTRACT; - return g_ObjFinalizeStartTime; -} - -void FinalizerThreadAbortOnTimeout() -{ - STATIC_CONTRACT_NOTHROW; - STATIC_CONTRACT_MODE_COOPERATIVE; - STATIC_CONTRACT_GC_TRIGGERS; - - { - // If finalizer thread is blocked because scheduler is running another task, - // or it is waiting for another thread, we first see if we get finalizer thread - // running again. - Thread::ThreadAbortWatchDog(); - } - - EX_TRY - { - Thread *pFinalizerThread = FinalizerThread::GetFinalizerThread(); - EPolicyAction action = GetEEPolicy()->GetActionOnTimeout(OPR_FinalizerRun, pFinalizerThread); - switch (action) - { - case eAbortThread: - GetEEPolicy()->NotifyHostOnTimeout(OPR_FinalizerRun, action); - pFinalizerThread->UserAbort(Thread::TAR_Thread, - EEPolicy::TA_Safe, - INFINITE, - Thread::UAC_FinalizerTimeout); - break; - case eRudeAbortThread: - GetEEPolicy()->NotifyHostOnTimeout(OPR_FinalizerRun, action); - pFinalizerThread->UserAbort(Thread::TAR_Thread, - EEPolicy::TA_Rude, - INFINITE, - Thread::UAC_FinalizerTimeout); - break; - case eUnloadAppDomain: - { - AppDomain *pDomain = pFinalizerThread->GetDomain(); - pFinalizerThread->UserAbort(Thread::TAR_Thread, - EEPolicy::TA_Safe, - INFINITE, - Thread::UAC_FinalizerTimeout); - } - break; - case eRudeUnloadAppDomain: - { - AppDomain *pDomain = pFinalizerThread->GetDomain(); - pFinalizerThread->UserAbort(Thread::TAR_Thread, - EEPolicy::TA_Rude, - INFINITE, - Thread::UAC_FinalizerTimeout); - } - break; - case eExitProcess: - case eFastExitProcess: - case eRudeExitProcess: - case eDisableRuntime: - GetEEPolicy()->NotifyHostOnTimeout(OPR_FinalizerRun, action); - EEPolicy::HandleExitProcessFromEscalation(action, HOST_E_EXITPROCESS_TIMEOUT); - _ASSERTE (!"Should not get here"); - break; - default: - break; - } - } - EX_CATCH - { - } - EX_END_CATCH(SwallowAllExceptions); -} - enum WorkType { WT_UnloadDomain = 0x1, |