Finalización de un proceso

La terminación de un proceso tiene los siguientes resultados:

  • Los subprocesos restantes del proceso se marcan para la finalización.
  • Se liberan todos los recursos asignados por el proceso.
  • Todos los objetos kernel están cerrados.
  • El código de proceso se quita de la memoria.
  • Se establece el código de salida del proceso.
  • Se señala el objeto de proceso.

Mientras los identificadores abiertos de los objetos kernel se cierran automáticamente cuando finaliza un proceso, los propios objetos existen hasta que se cierran todos los identificadores abiertos. Por lo tanto, un objeto permanecerá válido después de que un proceso que lo use finalice si otro proceso tiene un identificador abierto.

La función GetExitCodeProcess devuelve el estado de finalización de un proceso. Mientras se ejecuta un proceso, su estado de finalización es STILL_ACTIVE. Cuando finaliza un proceso, su estado de finalización cambia de STILL_ACTIVE al código de salida del proceso.

Cuando finaliza un proceso, se señala el estado del objeto de proceso, liberando los subprocesos que habían estado esperando a que finalice el proceso. Para obtener más información sobre la sincronización, consulte Sincronización de la ejecución de varios subprocesos.

Cuando el sistema termina un proceso, no finaliza ningún proceso secundario que el proceso haya creado. La terminación de un proceso no genera notificaciones para los procedimientos de enlace de WH_CBT.

Use la función SetProcessShutdownParameters para especificar determinados aspectos de la terminación del proceso durante el apagado del sistema, como cuando un proceso debe finalizar en relación con los demás procesos del sistema.

Cómo finalizan los procesos

Un proceso se ejecuta hasta que se produce uno de los siguientes eventos:

  • Cualquier subproceso del proceso llama a la función ExitProcess . Tenga en cuenta que alguna implementación de la biblioteca en tiempo de ejecución de C (CRT) llama a ExitProcess si el subproceso principal del proceso devuelve.
  • El último subproceso del proceso finaliza.
  • Cualquier subproceso llama a la función TerminateProcess con un identificador para el proceso.
  • Para los procesos de consola, el controlador de control de consola predeterminado llama a ExitProcess cuando la consola recibe una señal CTRL+C o CTRL+BREAK.
  • El usuario cierra el sistema o cierra la sesión.

No finalice un proceso a menos que sus subprocesos estén en estados conocidos. Si un subproceso está esperando en un objeto kernel, no se finalizará hasta que se haya completado la espera. Esto puede hacer que la aplicación deje de responder.

El subproceso principal puede evitar la terminación de otros subprocesos al dirigirlos para llamar a ExitThread antes de hacer que el proceso finalice (para obtener más información, vea Finalizar un subproceso). El subproceso principal todavía puede llamar a ExitProcess después para asegurarse de que todos los subprocesos están terminados.

El código de salida de un proceso es el valor especificado en la llamada a ExitProcess o TerminateProcess, o bien el valor devuelto por la función main o WinMain del proceso. Si un proceso finaliza debido a una excepción grave, el código de salida es el valor de la excepción que provocó la terminación. Además, este valor se usa como código de salida para todos los subprocesos que se estaban ejecutando cuando se produjo la excepción.

Si ExitProcess finaliza un proceso, el sistema llama a la función de punto de entrada de cada DLL adjunta con un valor que indica que el proceso se separa del archivo DLL. Los archivos DLL no se notifican cuando TerminateProcess finaliza un proceso. Para obtener más información sobre los archivos DLL, consulte Bibliotecas de vínculos dinámicos.

Si TerminateProcess finaliza un proceso, todos los subprocesos del proceso se finalizan inmediatamente sin posibilidad de ejecutar código adicional. Esto significa que el subproceso no ejecuta código en bloques de controladores de terminación. Además, no se notifica a ningún archivo DLL adjunto que el proceso se desasocie. Si necesita que un proceso finalice otro proceso, los pasos siguientes proporcionan una mejor solución:

  • Haga que ambos procesos llamen a la función RegisterWindowMessage para crear un mensaje privado.

  • Un proceso puede finalizar el otro mediante la difusión de un mensaje privado mediante la función BroadcastSystemMessage de la siguiente manera:

     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
    
  • El proceso que recibe el mensaje privado llama a ExitProcess para finalizar su ejecución.

La ejecución de las funciones ExitProcess, ExitThread, CreateThread, CreateRemoteThread y CreateProcess se serializa dentro de un espacio de direcciones. Se aplican las restricciones que se indican a continuación:

  • Durante las rutinas de inicio del proceso y de inicialización de DLL, se pueden crear nuevos subprocesos, pero no comienzan la ejecución hasta que finalice la inicialización de DLL para el proceso.
  • Solo un subproceso a la vez puede estar en una rutina de inicialización o desasociación de DLL.
  • La función ExitProcess no devuelve hasta que no haya ningún subproceso en sus rutinas de inicialización o desasociación de DLL.