2008-09-10 5 views
57

En C++ aplicación de Windows, pongo en marcha varios procesos de larga ejecución niño (Actualmente uso CreateProcess (...) para hacer esto.¿Cómo destruyo automáticamente los procesos hijos en Windows?

Quiero que los procesos secundarios que se cierre automáticamente si mis principales procesos se bloquea o es cerrado

Debido al requisito de que esto debe funcionar para un bloqueo del "principal", creo que esto tendría que hacerse utilizando alguna API/función del sistema operativo. De modo que todos los procesos "secundarios" se limpian.

¿Cómo puedo hacer esto?

Respuesta

64

La API de Windows admite objetos denominados "Objetos de trabajo". El siguiente código creará un "trabajo" que está configurado para cerrar todos los procesos cuando finaliza la aplicación principal (cuando se limpian sus identificadores). Este código sólo se debe ejecutar una vez .:

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); 
    } 
} 

Luego, cuando se crea cada proceso hijo, ejecute el siguiente código para poner en marcha cada niño cada proceso y añadirlo al objeto de trabajo:

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 NOTA: Consulte AssignProcessToJobObject always return "access denied" on Vista si encuentra problemas de acceso denegado con AssignProcessToObject() en vista.

+0

Para responder a su pregunta en el comentario: Sí, debe cerrar Close cuando ya no necesite el identificador. –

+0

Sí, ¿pero terminará así el trabajo? –

+1

No, no lo creo. JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE hace que el trabajo finalice cuando se cierre el último identificador * job *, los identificadores de proceso no deberían marcar la diferencia. ¿Lo has probado? –

-2

Probablemente tengas que mantener una lista de los procesos que inicias y matarlos uno por uno cuando salgas de tu programa. No estoy seguro de los detalles de hacer esto en C++, pero no debería ser difícil. La parte difícil probablemente sea asegurar que los procesos secundarios se cierren en caso de una falla de la aplicación. .Net tiene la capacidad de agregar una función que recibe cuando se produce una excepción no controlada. No estoy seguro si C++ ofrece las mismas capacidades.

+3

>> si mis procesos principales bloquean –

0

Puede mantener en ejecución un proceso de vigilancia independiente. Su única tarea es observar el espacio de proceso actual para detectar situaciones como las que describes. Incluso podría relanzar la aplicación original después de un bloqueo o proporcionar diferentes opciones al usuario, recopilar información sobre depuración, etc. Simplemente trate de mantenerlo lo suficientemente simple para que no necesite un segundo perro guardián para ver el primero.

5

Una solución algo hackosa sería que el proceso principal se adjunte a cada niño como un depurador (use DebugActiveProcess). Cuando un depurador finaliza, todos sus procesos de depuración finalizan también.

Una mejor solución (suponiendo que haya escrito también los procesos secundarios) sería hacer que los procesos secundarios supervisen el elemento primario y lo eliminen si desaparecen.

+2

En lugar de tener que llamar a DebugActiveProcess, puede simplemente pasar DEBUG_PROCESS como uno de los indicadores de creación a CreateProcess. Menos código de esa manera. – mrduclaw

-2

Puede encapsular cada proceso en un objeto C++ y mantener una lista de ellos en alcance global. Los destructores pueden cerrar cada proceso. Eso funcionará bien si el programa sale normalmente pero se bloquea, todas las apuestas están apagadas.

Aquí está un ejemplo aproximado:

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

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

private: 
    HANDLE _hProcess; 
}; 

std::list<myprocess> allprocesses; 

Entonces cada vez que inicie una, llame allprocessess.push_back (hProcess);

+2

>> si mis procesos principales se bloquean –

-4

Justo al lado de la parte superior de mi cabeza:

  • ¿Usted ha considerado el uso de hilos en lugar de los procesos?
  • Intente pasar el controlador del subproceso/proceso principal a los procesos secundarios y haga que esperen en ese identificador. Esto funciona para subprocesos, ya que la espera en un identificador de subproceso espera hasta que el subproceso finaliza y finaliza. No estoy seguro de si funcionará para los procesos; debería verificar MSDN para verificar esto.
3

Windows Job Objects parece un buen lugar para comenzar. El nombre del objeto de trabajo debería ser conocido o transferido a los hijos (o heredar el identificador). Los niños necesitarían ser notificados cuando el padre muera, ya sea a través de un "latido" del IPC fallido o simplemente WFMO/WFSO en el manejo del proceso de los padres. En ese punto, cualquier proceso secundario podría TermianteJobObject para derribar a todo el grupo.

+0

En su lugar, un proceso secundario solo puede WFMO/WFSO en el controlador primario y se cierra a sí mismo. Siempre que cada proceso secundario lo haga, no hay necesidad de un objeto de trabajo. – dkrikun

Cuestiones relacionadas