2010-01-22 7 views
1

Résumé: J'ai besoin d'un moyen de déterminer si un processus Windows que j'ai généré via _spawnl et que je communique avec les FD de _pipe est mort.Détection de la mort du processus engendré à l'aide de la fenêtre CRT

Détails:

J'utilise la fonction CRT bas niveau dans Windows (_eof, _read) pour communiquer avec un processus qui a été donné naissance via un appel à _spawnl (avec le P_NOWAIT) drapeau. J'utilise _pipe pour créer des descripteurs de fichiers pour communiquer avec ce processus engendré et transmettre ces descripteurs (le FD #) à la ligne de commande.

Il est important de mentionner que je ne contrôle pas le processus engendré. C'est une boîte noire pour moi.

Il s'avère que le processus que nous sommes en train de générer se bloque occasionnellement. J'essaie de rendre mon code robuste en détectant le crash. Malheureusement, je ne peux pas voir un moyen de le faire. Il me semble raisonnable de penser qu'un appel à _eof ou _read sur l'un de ces descripteurs retournerait un statut d'erreur (-1) si le processus était mort.

Malheureusement, ce n'est pas le cas. Il semble que les descripteurs ont une vie propre indépendamment du processus engendré. Donc, même si le processus à l'autre extrémité est mort, je n'obtiens aucun statut d'erreur sur le descripteur de fichier que j'utilise pour communiquer avec lui.

J'ai le PID pour le processus imbriqué (renvoyé par l'appel _spanwnl) mais je ne vois rien de ce que je peux faire avec ça. Mon code fonctionne vraiment bien sauf pour une chose. Je ne peux pas détecter si le processus engendré est simplement occupé à me calculer une réponse ou est mort.

Si je peux utiliser les informations de _pipe et _spawnl pour déterminer si le processus engendré est mort, je serai en or.

Suggestions très bienvenues.

Merci d'avance.

MISE À JOUR: J'ai trouvé une solution assez simple et l'ai ajoutée comme réponse sélectionnée.

+0

Pour être clair, en fonctionnement normal, les pistes de processus donné naissance indéfiniment (pour des raisons pratiques). Donc, un appel à _cwait n'est pas bon. Je ne veux pas attendre jusqu'à ce qu'il se termine parce que, dans des circonstances normales, cela bloquerait mon programme. Je veux juste savoir * si * ça s'est terminé. –

Répondre

1

Voir How to know child process status and resource usage on windows?

Vous pouvez simplement utiliser WaitForSingleObject sur la poignée de retour spawnl; ça fonctionne bien pour moi. Il semble que vous ayez déjà essayé, mais peut-être que je ne comprends pas vos réponses.

exemple de code qui génère un processus et attend qu'elle se termine sans utiliser _P_WAIT:

HANDLE hProcess = (HANDLE) _spawnl(_P_NOWAIT, "slave.exe", "slave.exe", NULL); 
while(1) 
{ 
    Sleep(100); 
    if (WaitForSingleObject(hProcess, 0) == WAIT_OBJECT_0) 
    { 
    break; 
    } 
} 
1

Vous devrez remonter la chaîne alimentaire si vous voulez être capable de détecter la sortie du processus. L'API Win32 CreateProcess() native peut vous renvoyer un HANDLE, vous pouvez l'utiliser dans l'API WaitForSingleObject() pour attendre ou tester si le processus s'est arrêté. Si vous pouvez obtenir le PID, vous pouvez utiliser OpenProcess() pour obtenir le HANDLE dont vous avez besoin.

Une autre approche consiste à utiliser _P_WAIT pour en faire un appel synchrone. Cela nécessitera un fil.

+0

Malheureusement, cela impliquerait de réécrire complètement une bonne quantité de code. Si je dois le faire, je suppose que je le ferai. Une chose qui m'est venue à l'esprit depuis que j'ai posté la question est de savoir si je peux accéder aux descripteurs de fichiers stdin et stdout du processus enfant créé via spawnl. Si oui, je pourrais vérifier * ces * pour voir s'ils retournent des codes d'erreur (puisqu'ils sont plus étroitement liés au processus engendré). Je n'ai juste pas compris comment les obtenir (encore). –

+0

Ma première coupe à ce P_WAIT utilisé, mais le problème est qu'il bloque lorsque le processus de spawn meurt et il ne revient jamais. Donc, même si j'ai implémenté dans le thread (ce qui n'est pas vraiment une exigence pour moi, je peux attendre la réponse), le thread va juste se bloquer. –

+0

Eh bien, c'est du code couper-coller: http://msdn.microsoft.com/fr-fr/library/ms682499%28VS.85%29.aspx –

0

Merci à nobugz pour beaucoup de bons conseils. Je n'ai pas fini par emprunter la voie de la «remontée de la chaîne alimentaire», alors j'écris ceci comme une réponse séparée, mais c'est surtout le résultat de ses commentaires. J'ai utilisé mon appel existant à spawnl. Il s'est avéré que cela était possible parce que quand il est appelé avec le mode P_NOWAIT, la valeur de retour est en fait la même que OpenProcess. Ceci est déroutant car spawnl a un type de retour intptr_t alors que OpenProcess a un type de retour de HANDLE. Mais ils sont équivalents (au moins sur la base de mes tests). Sachant cela, je n'étais toujours pas sorti du bois. J'avais besoin d'un moyen fiable de déterminer si le processus était toujours en cours. Tous les divers appels que j'ai faits en utilisant le handle de processus (par exemple GetModuleBaseName) ont réussi même lorsque le processus était mort.En fin de compte, j'ai eu recours à GetProcessId (avec mon handle de processus) pour obtenir l'ID du processus puis appeler EnumerateProcesses et explorer les résultats renvoyés pour voir si l'un de ces processus partageait le même ID de processus.

Je reconnais que l'utilisation d'API de plus haut niveau (comme le suggère nobugz) est probablement la meilleure façon de procéder. Dans mon cas, j'avais déjà tout le code qui fonctionnait et je n'avais besoin que de déterminer si le processus imbriqué était toujours en cours d'exécution, donc j'ai adopté une approche minimaliste.

Merci encore à nobugz pour toutes les suggestions utiles.