2009-11-25 15 views
5

Vorrei eseguire processi secondari arbitrari basati su console e gestirli da un singolo processo master. I sottoprocessi basati su console comunicano tramite stdin, stdout e stderr e, se li si esegue in una console originale, terminano in modo pulito quando si preme CTRL + C. Alcuni di essi potrebbero in effetti essere un albero di processi, come uno script batch che esegue un eseguibile che a sua volta può eseguire un altro eseguibile per fare un po 'di lavoro. Vorrei reindirizzare il loro I/O standard (ad esempio, in modo che possa mostrare il loro output in una finestra della GUI) e in determinate circostanze inviare loro un evento CTRL + C in modo che possano rinunciare e terminare in modo pulito.Invia CTRL + C per subprocess tree su Windows

I seguenti due diagrammi mostrano prima la struttura normale: un processo principale ha quattro sottoprocessi di lavoro e alcuni di questi hanno i propri sottoprocessi; e poi cosa dovrebbe accadere quando uno dei lavoratori deve essere fermato - e tutti i suoi figli dovrebbero ottenere l'evento CTRL + C, ma nessun altro processo dovrebbe ricevere l'evento CTRL + C.

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

Inoltre, preferirei di gran lunga che non ci sono finestre in più visibili per l'utente.

Ecco che cosa ho provato (notare che io sto lavorando in Python, ma soluzioni per C sarebbe ancora utile):

  • Deposizione un processo intermedio in più con CREATE_NEW_CONSOLE, e poi averlo deporre le uova la processo di lavoro. Poi chiama lo GenerateConsoleCtrlEvent (CTRL_C_EVENT, 0) quando vogliamo uccidere il lavoratore. Sfortunatamente, CREATE_NEW_CONSOLE sembra impedirmi di reindirizzare i canali di I/O standard, quindi non mi rimane un modo semplice per riportare l'output al programma principale.
  • Creazione di un processo intermedio aggiuntivo con CREATE_NEW_PROCESS_GROUP e successiva creazione del processo di lavoro. Poi chiama lo GenerateConsoleCtrlEvent (CTRL_C_EVENT, 0) quando vogliamo uccidere il lavoratore. In qualche modo, questo riesce a inviare il CTRL + C solo al processo principale, che è completamente inutile. A un esame più attento, GenerateConsoleCtrlEvent dice che CTRL + C non può essere inviato ai gruppi di processi.
  • Generazione del sottoprocesso con CREATE_NEW_PROCESS_GROUP. Quindi chiama lo GenerateConsoleCtrlEvent (CTRL_BREAK_EVENT, pid) per uccidere il lavoratore. Questo non è l'ideale, perché CTRL + BREAK è meno amichevole di CTRL + C e probabilmente si tradurrà in una conclusione più caotica. (Ad esempio, se si tratta di un processo Python, nessun KeyboardInterrupt può essere catturato e nessun blocco finale può essere eseguito.)

C'è un buon modo per fare ciò che voglio? Posso vedere che potrei teoricamente costruire al primo tentativo e trovare un altro modo di comunicare tra i processi, ma sono preoccupato che si rivelerà estremamente imbarazzante. Ci sono buoni esempi di altri programmi che ottengono lo stesso effetto? Sembra così semplice che non può essere un requisito così raro.

risposta

1

Non so sulla gestione/reindirizzamento di stdin et. al., ma per gestire l'albero di sottoprocesso hai considerato l'utilizzo dell'API di Windows Job Objects?

Ci sono molte altre domande sulla gestione degli alberi dei processi (How do I automatically destroy child processes in Windows?Performing equivalent of “Kill Process Tree” in c++ on windows) e sembra il metodo più pulito se è possibile utilizzarlo.

Il capitolo 5 di Windows Via C/C++ by Jeffery Richter ha una buona discussione sull'utilizzo di CreateJobObject e delle relative API.

+0

Ho esaminato gli oggetti di lavoro in precedenza, ma l'unico meccanismo che forniscono per arrestare il lavoro consiste nel terminare forzatamente i suoi processi. La ragione per cui voglio inviare CTRL + C è dare ai processi un'opportunità per finire in modo pulito. Nota che i gruppi di processi e CTRL_BREAK_EVENT fanno un lavoro soddisfacente se non mi interessa specificamente l'invio di un CTRL + C. – Weeble

Problemi correlati