Comment puis-je détruisent automatiquement les processus enfants dans Windows?

StackOverflow https://stackoverflow.com/questions/53208

  •  09-06-2019
  •  | 
  •  

Question

En C++ application Windows, je lance plusieurs long de l'exécution de processus enfants (actuellement j'utilise la fonction CreateProcess(...) pour ce faire.

Je veux que le processus enfant sera automatiquement fermé si mes principaux processus se bloque ou qu'il est fermé.

En raison de l'exigence que cela doit travailler pour un crash de la "mère", je crois que cela devrait être fait en utilisant l'API/fonctionnalité du système d'exploitation.Afin que tous les "enfants" des processus de nettoyage.

Comment dois-je faire?

Était-ce utile?

La solution

L'API Windows prend en charge les objets appelés "Objets".Le code suivant va créer un "travail" qui est configuré pour arrêter tous les processus de l'application principale se termine (lorsque les poignées sont nettoyées).Ce code ne doit être exécuté qu'une fois.:

HANDLE ghJob = CreateJobObject( NULL, NULL); // GLOBAL
if( ghJob == NULL)
{
    ::MessageBox( 0, "Could not create job object", "TEST", MB_OK);
}
else
{
    JOBOBJECT_EXTENDED_LIMIT_INFORMATION jeli = { 0 };

    // Configure all child processes associated with the job to terminate when the
    jeli.BasicLimitInformation.LimitFlags = JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE;
    if( 0 == SetInformationJobObject( ghJob, JobObjectExtendedLimitInformation, &jeli, sizeof(jeli)))
    {
        ::MessageBox( 0, "Could not SetInformationJobObject", "TEST", MB_OK);
    }
}

Ensuite, lors de chaque processus enfant est créé, exécutez le code suivant pour lancer à chaque enfant de chaque processus et de l'ajouter à l'objet de travail:

STARTUPINFO info={sizeof(info)};
PROCESS_INFORMATION processInfo;

// Launch child process - example is notepad.exe
if (::CreateProcess( NULL, "notepad.exe", NULL, NULL, TRUE, 0, NULL, NULL, &info, &processInfo))
{
    ::MessageBox( 0, "CreateProcess succeeded.", "TEST", MB_OK);
    if(ghJob)
    {
        if(0 == AssignProcessToJobObject( ghJob, processInfo.hProcess))
        {
            ::MessageBox( 0, "Could not AssignProcessToObject", "TEST", MB_OK);
        }
    }

    // Can we free handles now? Not sure about this.
    //CloseHandle(processInfo.hProcess); 
    CloseHandle(processInfo.hThread);
}

VISTA NOTE:Voir AssignProcessToJobObject toujours revenir "accès refusé" sur Vista si vous rencontrez des refus d'accès des problèmes avec AssignProcessToObject() sur vista.

Autres conseils

Un peu hackish solution serait que le processus père d'associer à chaque enfant comme un débogueur (utilisation DebugActiveProcess).Lorsqu'un débogueur met fin à tous ses programme débogué les processus sont terminés ainsi.

Une meilleure solution (en supposant que vous avez écrit, l'enfant, le processus d') serait d'avoir l'enfant, les processus de surveiller la mère et de sortie si elle s'en va.

Windows Objets semble être un bon endroit pour commencer.Le nom de l'Objet de Travail devrait être bien connu, ou transmis à des enfants (ou d'hériter de la poignée).Les enfants auraient besoin d'être d'avis quand la mère meurt, soit par l'intermédiaire d'un échec de la CIB "battement de cœur" ou tout simplement WFMO/WFSO sur le parent du handle de processus.À ce point, tout le processus enfant pourrait TermianteJobObject mettre à bas l'ensemble du groupe.

Vous pouvez garder un chien de garde processus en cours d'exécution.Sa seule tâche est de regarder le processus actuel de l'espace de repérer de telles situations que vous décrivez.Il pourrait même relancer l'application d'origine après un crash ou de fournir des différentes options pour l'utilisateur, de recueillir des informations de débogage, etc.Juste essayer de le garder assez simple de sorte que vous n'avez pas besoin d'un deuxième chien de garde de regarder le premier.

Vous auriez probablement à garder une liste des processus de commencer, et de les tuer un par un lorsque vous quittez votre programme.Je ne suis pas sûr de la spécificité de le faire en C++, mais il ne devrait pas être dur.La partie la plus difficile sera probablement s'assurer que les processus enfants sont à l'arrêt dans le cas d'un crash de l'application..Net a la possibilité d'ajouter une fonction qui est appelée lorsqu'une exception non gérée se produit.Je ne suis pas sûr si C++ offre les mêmes capacités.

Vous pourriez encapsuler chaque processus dans un objet C++ et de garder une liste d'entre eux dans la portée globale.Les destructeurs peuvent l'arrêt de chaque processus.Qui fonctionnera bien si le programme se termine normalement, mais il se bloque, tous les paris sont éteints.

Voici un exemple grossier:

class myprocess
{
public:
    myprocess(HANDLE hProcess)
        : _hProcess(hProcess)
    { }

    ~myprocess()
    {
        TerminateProcess(_hProcess, 0);
    }

private:
    HANDLE _hProcess;
};

std::list<myprocess> allprocesses;

Alors à chaque fois que vous lancez un, appelez allprocessess.push_back(hProcess);

Juste à côté de ma tête:

  • Avez-vous envisagé d'utiliser des threads au lieu de processus?
  • Essayer de passer la poignée de la principale thread/processus à l'enfant de processus et de les amener à attendre sur cette poignée.Cela fonctionne pour les threads, comme en attente sur un fil poignée attend jusqu'à ce que le thread se termine et les sorties.Sais pas trop si ça va marcher pour les processus, consultez MSDN pour vérifier cela.
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top