zombie - Come faccio a distruggere automaticamente i processi figli in Windows?




unix processi (5)

È possibile incapsulare ogni processo in un oggetto C ++ e conservarne un elenco nell'ambito globale. I distruttori possono chiudere ogni processo. Funzionerà bene se il programma esce normalmente ma si blocca, tutte le scommesse sono disattivate.

Ecco un esempio approssimativo:

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

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

private:
    HANDLE _hProcess;
};

std::list<myprocess> allprocesses;

Quindi, quando ne lanci uno, chiama allprocessess.push_back (hProcess);

Nell'app C ++ per Windows, lancio diversi processi figlio con esecuzione prolungata (al momento utilizzo CreateProcess (...) per fare ciò.

Voglio che i processi figli vengano automaticamente chiusi se i miei processi principali si bloccano o vengono chiusi.

A causa del requisito che questo deve funzionare per un arresto anomalo del "genitore", credo che questo dovrebbe essere fatto utilizzando alcune API / funzionalità del sistema operativo. In modo che tutti i processi "figlio" vengano ripuliti.

Come faccio a fare questo?


È possibile mantenere in esecuzione un processo di watchdog separato. Il suo unico compito è osservare lo spazio del processo corrente per individuare situazioni come quelle che descrivi. Potrebbe persino riavviare l'applicazione originale dopo un arresto anomalo o fornire diverse opzioni all'utente, raccogliere informazioni di debug, ecc. Basta provare a mantenerlo abbastanza semplice in modo da non aver bisogno di un secondo cane da guardia per guardare il primo.


L'API di Windows supporta oggetti denominati "Oggetti lavoro". Il codice seguente creerà un "job" che è configurato per arrestare tutti i processi quando l'applicazione principale termina (quando gli handle vengono ripuliti). Questo codice dovrebbe essere eseguito una volta sola .:

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

Quindi, quando viene creato ogni processo figlio, eseguire il seguente codice per avviare ogni processo figlio e aggiungerlo all'oggetto lavoro:

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: Vedi AssignProcessToJobObject restituisce sempre "accesso negato" su Vista se si verificano problemi di accesso negati con AssignProcessToObject () su Vista.


Probabilmente dovresti tenere un elenco dei processi che inizi e eliminarli uno alla volta quando esci dal programma. Non sono sicuro delle specifiche di questo in C ++, ma non dovrebbe essere difficile. La parte difficile sarebbe probabilmente garantire che i processi figli vengano arrestati in caso di arresto anomalo dell'applicazione. .Net ha la possibilità di aggiungere una funzione che viene chiamata quando si verifica un'eccezione non gestita. Non sono sicuro che C ++ offra le stesse funzionalità.


Windows Job Objects sembra un buon punto di partenza. Il nome dell'oggetto Job dovrebbe essere noto o passato ai figli (o ereditare l'handle). I bambini dovrebbero essere avvisati quando il genitore muore, sia attraverso un "battito cardiaco" IPC fallito o semplicemente WFMO / WFSO sull'handle del processo del genitore. A quel punto qualsiasi processo figlio potrebbe TermianteJobObject per abbattere l'intero gruppo.







process