Encerrando um processo

Encerrar um processo tem os seguintes resultados:

  • Todos os threads restantes no processo são marcados para encerramento.
  • Todos os recursos alocados pelo processo são liberados.
  • Todos os objetos kernel são fechados.
  • O código do processo é removido da memória.
  • O código de saída do processo está definido.
  • O objeto de processo é sinalizado.

Embora os identificadores abertos para objetos kernel sejam fechados automaticamente quando um processo é encerrado, os próprios objetos existem até que todos os identificadores abertos para eles sejam fechados. Portanto, um objeto permanecerá válido após um processo que o está usando terminar se outro processo tiver um identificador aberto para ele.

A função GetExitCodeProcess retorna a status de encerramento de um processo. Enquanto um processo está em execução, seu status de encerramento é STILL_ACTIVE. Quando um processo é encerrado, sua terminação status muda de STILL_ACTIVE para o código de saída do processo.

Quando um processo é encerrado, o estado do objeto de processo fica sinalizado, liberando todos os threads que estavam aguardando o término do processo. Para obter mais informações sobre sincronização, consulte Sincronizando a execução de vários threads.

Quando o sistema está encerrando um processo, ele não encerra nenhum processo filho que o processo tenha criado. Encerrar um processo não gera notificações para WH_CBT procedimentos de gancho.

Use a função SetProcessShutdownParameters para especificar determinados aspectos do encerramento do processo no desligamento do sistema, como quando um processo deve terminar em relação aos outros processos no sistema.

Como os processos são encerrados

Um processo é executado até que ocorra um dos seguintes eventos:

  • Qualquer thread do processo chama a função ExitProcess . Observe que alguma implementação da CRT (biblioteca de tempo de execução) C chamará ExitProcess se o thread primário do processo retornar.
  • O último thread do processo é encerrado.
  • Qualquer thread chama a função TerminateProcess com um identificador para o processo.
  • Para processos de console, o manipulador de controle de console padrão chama ExitProcess quando o console recebe um sinal CTRL+C ou CTRL+BREAK.
  • O usuário desliga o sistema ou faz logoff.

Não encerre um processo, a menos que seus threads estejam em estados conhecidos. Se um thread estiver aguardando um objeto kernel, ele não será encerrado até que a espera seja concluída. Isso pode fazer com que o aplicativo pare de responder.

O thread primário pode evitar encerrar outros threads direcionando-os para chamar ExitThread antes de fazer com que o processo seja encerrado (para obter mais informações, consulte Encerrando um thread). O thread primário ainda pode chamar ExitProcess posteriormente para garantir que todos os threads sejam encerrados.

O código de saída de um processo é o valor especificado na chamada para ExitProcess ou TerminateProcess ou o valor retornado pela função main ou WinMain do processo. Se um processo for encerrado devido a uma exceção fatal, o código de saída será o valor da exceção que causou o encerramento. Além disso, esse valor é usado como o código de saída para todos os threads que estavam sendo executados quando a exceção ocorreu.

Se um processo for encerrado pelo ExitProcess, o sistema chamará a função de ponto de entrada de cada DLL anexada com um valor que indica que o processo está desanexando da DLL. As DLLs não são notificadas quando um processo é encerrado pelo TerminateProcess. Para obter mais informações sobre DLLs, consulte Bibliotecas de Vínculo Dinâmico.

Se um processo for encerrado pelo TerminateProcess, todos os threads do processo serão encerrados imediatamente sem nenhuma chance de executar código adicional. Isso significa que o thread não executa código em blocos de manipulador de terminação. Além disso, nenhuma DLL anexada é notificada de que o processo está sendo desanexado. Se você precisar que um processo encerre outro processo, as seguintes etapas fornecem uma solução melhor:

  • Faça com que ambos os processos chamem a função RegisterWindowMessage para criar uma mensagem privada.

  • Um processo pode encerrar o outro processo transmitindo uma mensagem privada usando a função BroadcastSystemMessage da seguinte maneira:

     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
    
  • O processo que recebe a mensagem privada chama ExitProcess para encerrar sua execução.

A execução das funções ExitProcess, ExitThread, CreateThread, CreateRemoteThread e CreateProcess é serializada em um espaço de endereço. As restrições a seguir se aplicam:

  • Durante a inicialização do processo e as rotinas de inicialização de DLL, novos threads podem ser criados, mas não iniciam a execução até que a inicialização da DLL seja concluída para o processo.
  • Somente um thread por vez pode estar em uma rotina de inicialização ou desanexação de DLL.
  • A função ExitProcess não retorna até que não haja threads em suas rotinas de inicialização ou desanexação de DLL.