2009-11-25 13 views
5

Me gustaría ejecutar subprocesos arbitrarios basados ​​en consola y administrarlos desde un solo proceso maestro. Los subprocesos basados ​​en la consola se comunican a través de stdin, stdout y stderr, y si los ejecuta en una consola original terminan limpiamente cuando presiona CTRL + C. Algunos de ellos pueden ser, de hecho, un árbol de procesos, como un script por lotes que ejecuta un ejecutable que a su vez puede ejecutar otro ejecutable para hacer algún trabajo. Me gustaría redirigir su E/S estándar (por ejemplo, para que pueda mostrar su salida en una ventana de GUI) y en ciertas circunstancias enviarles un evento CTRL + C para que se den por vencidos y terminen limpiamente.Enviar CTRL + C al árbol de subproceso en Windows

Los siguientes dos diagramas muestran primero la estructura normal: un proceso maestro tiene cuatro subprocesos de trabajo, y algunos de esos trabajadores tienen sus propios subprocesos; y luego, ¿qué debería pasar cuando uno de los trabajadores necesita detenerse? Tanto él como todos sus hijos deberían obtener el evento CTRL + C, , pero ningún otro proceso debería recibir el evento CTRL + C.

Process diagram http://pics.livejournal.com/clockworksaint/pic/0007z5yr/s640x480.png

Además, me gusta mucho más que no hay ventanas adicionales visibles para el usuario.

Aquí es lo que he intentado (en cuenta que yo estoy trabajando en Python, pero las soluciones para C todavía sería útil):

  • desove un proceso intermedio adicional con CREATE_NEW_CONSOLE, y luego tener que generar el proceso de trabajo Luego haga que llame al GenerateConsoleCtrlEvent (CTRL_C_EVENT, 0) cuando queremos matar al trabajador. Desafortunadamente, CREATE_NEW_CONSOLE parece que me impide redirigir los canales de E/S estándar, por lo que no me queda una forma fácil de volver a enviar la salida al programa principal.
  • Engendrando un proceso intermedio adicional con CREATE_NEW_PROCESS_GROUP, y haciendo que genere el proceso de trabajo. Luego haga que llame al GenerateConsoleCtrlEvent (CTRL_C_EVENT, 0) cuando queremos matar al trabajador. De alguna manera, esto logra enviar el CTRL + C solo al proceso maestro, lo cual es completamente inútil. En una inspección más cercana, GenerateConsoleCtrlEvent dice que CTRL + C no se puede enviar a grupos de proceso.
  • Desove del subproceso con CREATE_NEW_PROCESS_GROUP. Luego, llame al GenerateConsoleCtrlEvent (CTRL_BREAK_EVENT, pid) para matar al trabajador. Esto no es ideal, porque CTRL + BREAK es menos amigable que CTRL + C y probablemente dará como resultado una terminación más desordenada. (Por ejemplo, si se trata de un proceso de Python, no se puede capturar KeyboardInterrupt y no se bloquean finalmente los bloques.)

¿Hay alguna manera de hacer lo que quiero? Veo que podría teóricamente construir en el primer intento y encontrar otra forma de comunicarme entre los procesos, pero me preocupa que resulte extremadamente incómodo. ¿Hay buenos ejemplos de otros programas que logran el mismo efecto? Parece tan simple que no puede ser un requisito tan poco común.

Respuesta

1

No sé sobre la gestión/redirección de stdin et. al., pero para gestionar el árbol de subproceso ¿ha considerado utilizar la aplicación Windows Job Objects?

Hay muchas otras preguntas sobre la gestión de árboles de proceso (How do I automatically destroy child processes in Windows?Performing equivalent of “Kill Process Tree” in c++ on windows) y parece el método más limpio si puede usarlo.

El capítulo 5 de Windows Via C/C++ by Jeffery Richter contiene una buena discusión sobre el uso de CreateJobObject y las API relacionadas.

+0

He visto objetos de trabajo antes, pero el único mecanismo que proporcionan para detener el trabajo es terminar a la fuerza sus procesos. El motivo por el que deseo enviar CTRL + C es darles a los procesos la oportunidad de terminar de forma limpia. Tenga en cuenta que los grupos de procesos y CTRL_BREAK_EVENT hacen un trabajo satisfactorio si no me importa enviar específicamente un CTRL + C. – Weeble