2009-11-20 74 views
0

J'ai rencontré une situation étrange où démarrer un pool d'applications à partir d'un service Windows (écrit en C#, démarrage automatique) en utilisant WMI ou ADSI immédiatement après le redémarrage du serveur se bloque.Le démarrage des pools d'applications avec WMI ADSI (C#) se bloque immédiatement après le redémarrage

Je vais décrire le problème:

Nous développons une grande application (Windows 2003 Server SP2, IIS 6.0) qui contient les principaux processus suivants (ces processus sont invoquaient & initialisé en utilisant une procédure de démarrage du service Windows lorsque 1) XServer1.exe, XServer2.exe - Ces processus sont des serveurs COM-Exe natifs, contiennent des logiques, mais fournissent principalement des objets COM à d'autres processus via DCOM (principalement les appels .NET2COM interOp & appels COM purs). Par exemple, certains des ASP «Application Scope static objects» classiques (w3wp.exe) sont des objets COM qui «vivent» dans ces processus.

2) dllhost.exe - il s'agit d'une application COM +. Certaines de nos DLL sont chargées dans ce processus qui agit comme un "serveur d'état" (la même idée que le serveur de sessions ASP.NET out-of-proc, mais pour les pages ASP classiques). 3) 3 pools d'applications IIS différents (nous les appellerons appPool1 \ 2 \ 3) - conteneurs de nos pages ASP, pages ASP.NET, services WCF, etc. Code (dlls C++ COM natifs & C#) dans ces Les pools d'applications (w3wp.exe) effectuent généralement des appels DCOM aux processus décrits dans (1) & (2). Seul AppPool1 peut être configuré en tant que Web Garden. Pour démarrer \ Arrêter notre application, nous avons écrit un service Windows (C#) qui contrôle ces procédures. Notre processus de service s'appelle XWinService.exe. Le service dépend des services Windows suivants (la liste a commencé avec les 4 premiers services, essais en cours ont fait la liste comme ça ...):

W3SVC

aspnet_state

COMSysApp

DcomLaunch

winmgmt

lanmanserver

lanmanworkstation

seclogon

Browser

TermService

Le résumé de la procédure d'arrêt de l'application (mis en œuvre par le service):

1) Arrêter les 3 pools d'applications IIS (appPool1 \ 2 \ 3) - Ceci est fait pour empêcher les processus w3wp.exe de sauter en vie lorsque l'application est arrêtée. Ceci est mis en œuvre avec WMI de C# (System.Management.dll)

2) Arrêt XServer1 \ 2.exe

3) Arrêter l'application COM + (Dllhost.exe).

Le résumé de la procédure de démarrage de l'application (mis en œuvre par le service):

1) Exécutez la procédure d'arrêt - Cela garantit qu'aucun hits HTTP réveilleront un processus w3wp.exe avant qu'il soit temps.

2) Appelle & Initialise les serveurs COM-Exe XServer1 \ 2.exe - L'initialisation est requise avant toute invocation w3wp.exe. Seulement après l'initialisation d'un objet, w3wp.exe peut accéder à ces serveurs. Ceci est implémenté par .NET2COM InterOp (éventuellement DCOM).

3) Invoque & a initialisé le processus dllhost.exe (application COM +) - implémenté par l'API de catalogue ComAdmin (C#).

4) Démarre nos 3 pools d'applications - Cela permet aux hits HTTP entrants de réactiver les processus w3wp.exe et de commencer à traiter les requêtes.

Ceci est le code C# qui est responsable de démarrer \ arrêter les pools d'applications (WMI). Ce code fonctionne dans nos processus de service (XWinService.exe):

ConnectionOptions co = new ConnectionOptions(); 
ManagementScope scope = new ManagementScope(@"\\localhost\root\MicrosoftIISV2", co); 
foreach (string appPool in AppPools) 
{ 
    string objPath = string.Format("IISApplicationPool.Name='W3SVC/AppPools/{0}'", appPool); 
    using (ManagementObject mc = new ManagementObject(objPath)) 
    { 
    mc.Scope = scope; 
    if (Operation.ToLower() == "start") 
    { 
    mc.InvokeMethod("Start", null, null); // ### The problematic line of code ### 
    } 
    else if (Operation.ToLower() == "stop") 
    { 
     mc.InvokeMethod("Stop", null, null); 
    } 
    else if (Operation.ToLower() == "recycle") 
    { 
    mc.InvokeMethod("Recycle", null, null); 
    } 

} 

} 

Maintenant la question:

Avant de redémarrer le serveur, le démarrage du service manuellement (à partir du services.msc outil) réussit sans aucun problème. aussi, l'arrêter est OK. Nous avons défini le service pour démarrer "Automatique", c'est-à-dire, démarrera lorsque le serveur (Win2K3 SP2) démarrera et redémarrera le serveur. Lorsque le serveur a démarré (l'écran de connexion est apparu), notre service était "bloqué" (status = "Starting") et ne JAMAIS (il pend pendant 2 jours!) Start.

Analyser les processus délectait ce qui suit:

1) Le processus XWinService.exe a été collé sur la ligne problématique de code (### au-dessus de ###). Ceci a pendu pendant 2 jours jusqu'à ce que nous ayons tué le processus. Veuillez noter: L'arrêt des pools d'applications (la procédure de démarrage commence par une procédure d'arrêt) ne s'est pas arrêté!

2) A partir d'un fichier DUMP pris (avec l'outil DebugDiag) de XWinService.exe pendant ce "hang" nous pouvons voir le thread qui attend. Ceci est la (native) trace de pile de celui-ci:

Thread 6 - System ID 2784 
Entry point mscorwks!Thread::intermediateThreadProc 
Create time 11/19/2009 1:40:05 PM 
Time spent in user mode 0 Days 00:00:00.078 
Time spent in kernel mode 0 Days 00:00:00.781 


This thread is making a COM call to multi-threaded apartment (MTA) in process 884 
Function Source 
ntdll!KiFastSystemCallRet 
ntdll!NtRequestWaitReplyPort+c 
rpcrt4!LRPC_CCALL::SendReceive+230 
rpcrt4!I_RpcSendReceive+24 
ole32!ThreadSendReceive+138 
ole32!CRpcChannelBuffer::SwitchAptAndDispatchCall+112 
ole32!CRpcChannelBuffer::SendReceive2+d3 
ole32!CAptRpcChnl::SendReceive+ab 
ole32!CCtxComChnl::SendReceive+1a9 
rpcrt4!NdrProxySendReceive+43 
rpcrt4!NdrClientCall2+206 
rpcrt4!ObjectStublessClient+8b 
rpcrt4!ObjectStubless+f 
…. 

Ce fil est appelant (via DCOM) un composant de processus 884, qui est svchost.exe, exécutant les services suivants: AeLookupSvc, AudioSrv, navigateur, cryptsvc , dmserver, EventSystem, helpvc, lanmanserver, lanmanworkstation, Calendrier, seclogon, SENS, ShellHWDetection, TrkWks, winmgmt, wuauserv, WZCSVC. Comme vous pouvez le voir, le service "winmgmt" (responsable de WMI) est en cours d'exécution et notre service en dépend, ainsi notre service démarrera après le démarrage de winmgmt (le même pour le service IIS W3SVC). Le processus svchost.exe (884) a été sauvegardé et nous pouvons voir un thread (en attente d'un appel DCOM à la fin) accéder au processus 2880 qui est - wmiprvse.exe (je suppose que c'est le serveur WMI. savoir si c'est pertinent, mais il y a eu 2 instances de ce processus). C'est la pile d'appel native du thread (dans svchost.exe):

 Thread 48 - System ID 3816 
Entry point wbemcore!CCoreQueue::_ThreadEntry 
Create time 11/19/2009 1:40:56 PM 
Time spent in user mode 0 Days 00:00:00.00 
Time spent in kernel mode 0 Days 00:00:00.00 


This thread is making a COM call to multi-threaded apartment (MTA) in process 2880 

Function Source 
ntdll!KiFastSystemCallRet 
ntdll!NtRequestWaitReplyPort+c 
rpcrt4!LRPC_CCALL::SendReceive+230 
rpcrt4!I_RpcSendReceive+24 
ole32!ThreadSendReceive+138 
ole32!CRpcChannelBuffer::SwitchAptAndDispatchCall+112 
ole32!CRpcChannelBuffer::SendReceive2+d3 
ole32!CAptRpcChnl::SendReceive+ab 
ole32!CCtxComChnl::SendReceive+1a9 
… 

3) Réglage de notre service « manuel » et le démarrer (manuellement - après la connexion au serveur ou à partir à distance à partir d'un serveur différent immédiatement après le redémarrage) est OK - rien se bloque.

4) Nous avons supprimé notre service (du registre!) Et placé un fichier batch dans le dossier "startup" de Windows. Ce fichier batch appelle le code du service, mais l'exécute comme un exécutable C# normal. Après le redémarrage du serveur, il se bloque également sur la même ligne de code problématique (encore ... pendant 2 jours jusqu'à ce que nous l'ayons tué).

5) L'utilisation d'ADSI (System.DirectoryServices) à la place de WMI a eu les mêmes résultats (démarrage des pools d'applications pendu!).

Nous avons été en train de creuser dans ce pour les 2 dernières semaines ...

Mes questions:

==========

1) Est-ce que quelqu'un rencontre le même problème?

2) Est-ce que quelqu'un sait pourquoi il se bloque? Existe-t-il une dépendance supplémentaire au service que nous devrions prendre en compte?

3) Quelqu'un a-t-il une solution à ce problème?

4) Pourquoi cela se produit-il après un redémarrage uniquement lorsque le service est réglé sur le démarrage "Automatique"? Si nous le faisons manuellement - tout est OK!

***** Petite mise à jour: **

Nous avons remarqué que sur les machines virtuelles (VMware stations) le service se bloque après le redémarrage pour une moyenne de ~ 40min, jusqu'à ce qu'il commence (note: il ne manque jamais de commencer, mais 40min est beaucoup trop). Un message du journal des événements est enregistré dans le journal des événements système indiquant que notre service a pendu pendant plus de 16 minutes (source: Service Control Manager, Event ID: 7044).

Sur les machines "normales" (métaux réels), le temps moyen avant le début du service est ~ 55 heures !!! Là encore, une entrée de journal d'événements est enregistrée comme décrit ci-dessus.

Les valeurs d'avergae ont été calculées à partir de 10 différents VMs & 8 différents serveurs "réels".

Répondre

0

Je ne vois personne avait répondu, mais je posterai quelques nouvelles de toute façon ...

Nous avons découvert que avant le début des pools d'applications, la mise en l'état de service « a commencé » et l'ouverture d'un Le nouveau thread (new Thread(...)) qui exécute le code ci-dessus (en démarrant les pools d'applications avec WMI) résout le problème.

C'est le pseudo-code de la méthode OnStart du service:

OnStart { 
    StopProcedure(); 

    InvokeInitXServer1And2(); //COM-Exe servers 

    InvokeInitCOMPlusApplication(); //dllhost.exe 

    SetServiceStatus(SERVICE_STARTED); 

    Thread worker = new Thread(new threadStart(IISAppPoolStartWMI); //Calls the code 
} 

Ceci est la seule façon dont le service commence dans un délai raisonnable (maximum de 3 min, moyenne de ~ 1,5 min de machines réelles et VMs à la fois!) Et un processus w3wp.exe est démarré.

Si quelqu'un a une explication pour cela (problèmes MTA \ STA?!?!?), Je serai heureux de le lire.