Arrêt d’un processus

La fin d’un processus a les résultats suivants :

  • Tous les threads restants du processus sont marqués pour l’arrêt.
  • Toutes les ressources allouées par le processus sont libérées.
  • Tous les objets du noyau sont fermés.
  • Le code de processus est supprimé de la mémoire.
  • Le code de sortie du processus est défini.
  • L’objet de processus est signalé.

Alors que les handles ouverts aux objets du noyau sont fermés automatiquement lorsqu’un processus se termine, les objets eux-mêmes existent jusqu’à ce que tous les handles ouverts d’eux soient fermés. Par conséquent, un objet reste valide après l’arrêt d’un processus qui l’utilise si un autre processus a un handle ouvert.

La fonction GetExitCodeProcess retourne la status d’arrêt d’un processus. Pendant l’exécution d’un processus, son status d’arrêt est STILL_ACTIVE. Lorsqu’un processus se termine, son arrêt status passe de STILL_ACTIVE au code de sortie du processus.

Lorsqu’un processus se termine, l’état de l’objet de processus est signalé, libérant tous les threads qui attendaient l’arrêt du processus. Pour plus d’informations sur la synchronisation, consultez Synchronisation de l’exécution de plusieurs threads.

Lorsque le système met fin à un processus, il n’arrête pas les processus enfants que le processus a créés. La fin d’un processus ne génère pas de notifications pour les procédures de hook WH_CBT.

Utilisez la fonction SetProcessShutdownParameters pour spécifier certains aspects de l’arrêt du processus à l’arrêt du système, par exemple quand un processus doit se terminer par rapport aux autres processus du système.

Comment les processus sont arrêtés

Un processus s’exécute jusqu’à ce que l’un des événements suivants se produise :

  • Tout thread du processus appelle la fonction ExitProcess . Notez que certaines implémentations de la bibliothèque d’exécution C (CRT) appellent ExitProcess si le thread principal du processus retourne.
  • Le dernier thread du processus se termine.
  • Tout thread appelle la fonction TerminateProcess avec un handle au processus.
  • Pour les processus console, le gestionnaire de contrôle de console par défaut appelle ExitProcess lorsque la console reçoit un signal CTRL+C ou CTRL+BREAK.
  • L’utilisateur arrête le système ou se déconnecte.

N’arrêtez pas un processus, sauf si ses threads sont dans des états connus. Si un thread est en attente sur un objet noyau, il n’est pas terminé tant que l’attente n’est pas terminée. Cela peut entraîner l’arrêt de la réponse de l’application.

Le thread principal peut éviter de mettre fin à d’autres threads en les dirigeant vers l’appel de ExitThread avant d’entraîner l’arrêt du processus (pour plus d’informations, voir Mettre fin à un thread). Le thread principal peut toujours appeler ExitProcess par la suite pour s’assurer que tous les threads sont terminés.

Le code de sortie d’un processus est soit la valeur spécifiée dans l’appel à ExitProcess ou TerminateProcess, soit la valeur retournée par la fonction main ou WinMain du processus. Si un processus est arrêté en raison d’une exception irrécupérable, le code de sortie est la valeur de l’exception à l’origine de l’arrêt. En outre, cette valeur est utilisée comme code de sortie pour tous les threads qui s’exécutent lorsque l’exception s’est produite.

Si un processus est terminé par ExitProcess, le système appelle la fonction de point d’entrée de chaque DLL jointe avec une valeur indiquant que le processus est en train de se détacher de la DLL. Les DLL ne sont pas averties lorsqu’un processus est arrêté par TerminateProcess. Pour plus d’informations sur les DLL, consultez Bibliothèques de liens dynamiques.

Si un processus est terminé par TerminateProcess, tous les threads du processus sont arrêtés immédiatement sans aucune chance d’exécuter du code supplémentaire. Cela signifie que le thread n’exécute pas de code dans les blocs de gestionnaire de terminaison. En outre, aucune DLL attachée n’est avertie que le processus est en cours de détachement. Si vous avez besoin qu’un processus termine un autre processus, les étapes suivantes fournissent une meilleure solution :

  • Les deux processus appellent la fonction RegisterWindowMessage pour créer un message privé.

  • Un processus peut arrêter l’autre processus en diffusant un message privé à l’aide de la fonction BroadcastSystemMessage comme suit :

     DWORD dwRecipients = BSM_APPLICATIONS;
        UINT uMessage = PM_MYMSG;
        WPARAM wParam = 0;
        LPARAM lParam = 0;
    
        BroadcastSystemMessage( 
            BSF_IGNORECURRENTTASK, // do not send message to this process
            &dwRecipients,         // broadcast only to applications
            uMessage,              // registered private message
            wParam,                // message-specific value
            lParam );              // message-specific value
    
  • Le processus de réception du message privé appelle ExitProcess pour arrêter son exécution.

L’exécution des fonctions ExitProcess, ExitThread, CreateThread, CreateRemoteThread et CreateProcess est sérialisée dans un espace d’adressage. Les restrictions suivantes s’appliquent :

  • Pendant le démarrage du processus et les routines d’initialisation de DLL, de nouveaux threads peuvent être créés, mais ils ne commencent pas l’exécution tant que l’initialisation de la DLL n’est pas terminée pour le processus.
  • Un seul thread à la fois peut se trouver dans une routine d’initialisation ou de détachement de DLL.
  • La fonction ExitProcess ne retourne pas tant qu’il n’y a pas de threads dans leurs routines d’initialisation de DLL ou de détachement.