nsresult NS_COM NS_ShutdownXPCOM(nsIServiceManager* servMgr)
NS_ShutdownXPCOM(nsIServiceManager* servMgr)
nsresult NS_COM NS_ShutdownXPCOM(nsIServiceManager* servMgr){    // Notify observers of xpcom shutting down    nsresult rv = NS_OK;    {        // Block it so that the COMPtr will get deleted before we hit        // servicemanager shutdown        nsCOMPtr<nsIObserverService> observerService =                 do_GetService("@mozilla.org/observer-service;1", &rv);        if (NS_SUCCEEDED(rv))        {            nsCOMPtr<nsIServiceManager> mgr;            rv = NS_GetServiceManager(getter_AddRefs(mgr));            if (NS_SUCCEEDED(rv))            {                (void) observerService->NotifyObservers(mgr,                                                        NS_XPCOM_SHUTDOWN_OBSERVER_ID,                                                        nsnull);            }        }    }    // grab the event queue so that we can process events one last time before exiting    nsCOMPtr <nsIEventQueue> currentQ;    {        nsCOMPtr<nsIEventQueueService> eventQService =                 do_GetService(kEventQueueServiceCID, &rv);        if (eventQService) {            eventQService->GetThreadEventQueue(NS_CURRENT_THREAD, getter_AddRefs(currentQ));        }    }    // XPCOM is officially in shutdown mode NOW    // Set this only after the observers have been notified as this    // will cause servicemanager to become inaccessible.    gXPCOMShuttingDown = PR_TRUE;#ifdef DEBUG_dougt    fprintf(stderr, "* * * * XPCOM shutdown. Access will be denied * * * * \n");#endif    // We may have AddRef'd for the caller of NS_InitXPCOM, so release it    // here again:    NS_IF_RELEASE(servMgr);    // Shutdown global servicemanager    if (nsComponentManagerImpl::gComponentManager) {        nsComponentManagerImpl::gComponentManager->FreeServices();    }    if (currentQ) {        currentQ->ProcessPendingEvents();        currentQ = 0;    }        nsProxyObjectManager::Shutdown();    // Release the directory service    NS_IF_RELEASE(nsDirectoryService::gService);    // Shutdown nsLocalFile string conversion    NS_ShutdownLocalFile();#ifdef XP_UNIX    NS_ShutdownNativeCharsetUtils();#endif    // Shutdown the timer thread and all timers that might still be alive before    // shutting down the component manager    nsTimerImpl::Shutdown();    CallExitRoutines();    // Shutdown xpcom. This will release all loaders and cause others holding    // a refcount to the component manager to release it.    if (nsComponentManagerImpl::gComponentManager) {        rv = (nsComponentManagerImpl::gComponentManager)->Shutdown();        NS_ASSERTION(NS_SUCCEEDED(rv), "Component Manager shutdown failed.");    } else        NS_WARNING("Component Manager was never created ...");    // Release our own singletons    // Do this _after_ shutting down the component manager, because the    // JS component loader will use XPConnect to call nsIModule::canUnload,    // and that will spin up the InterfaceInfoManager again -- bad mojo    XPTI_FreeInterfaceInfoManager();    // Finally, release the component manager last because it unloads the    // libraries:    if (nsComponentManagerImpl::gComponentManager) {      nsrefcnt cnt;      NS_RELEASE2(nsComponentManagerImpl::gComponentManager, cnt);      NS_WARN_IF_FALSE(cnt == 0, "Component Manager being held past XPCOM shutdown.");    }    nsComponentManagerImpl::gComponentManager = nsnull;#ifdef DEBUG    _FreeAutoLockStatics();#endif    ShutdownSpecialSystemDirectory();    EmptyEnumeratorImpl::Shutdown();    nsMemoryImpl::Shutdown();    nsThread::Shutdown();    NS_PurgeAtomTable();    NS_IF_RELEASE(gDebug);#ifdef NS_BUILD_REFCNT_LOGGING    nsTraceRefcntImpl::DumpStatistics();    nsTraceRefcntImpl::ResetStatistics();    nsTraceRefcntImpl::Shutdown();#endif#ifdef GC_LEAK_DETECTOR    // Shutdown the Leak detector.    NS_ShutdownLeakDetector();#endif    return NS_OK;}