Il processo figlio riceve SIGINT dei genitori

Ho un semplice programma che usa Qt Framework. Usa QProcess per eseguire RAR e comprimere alcuni file. Nel mio programma sto prendendo SIGINT e sto facendo qualcosa nel mio codice quando si verifica:

signal(SIGINT, &unix_handler); 

Quando si verifica SIGINT, controllo se il processo RAR è terminato, e se non lo aspetto aspetterò … Il problema è che (penso) il processo RAR ha anche ottenuto SIGINT che era destinato al mio programma e si chiude prima ha compresso tutti i file.

Esiste un modo per eseguire il processo RAR in modo che non riceva SIGINT quando il mio programma lo riceve?

Grazie

Se stai generando SIGINT con Ctrl-c su un sistema Unix, il segnale viene inviato all’intero gruppo di processi .

È necessario utilizzare setpgid o setsid per mettere il processo secondario in un gruppo di processi diverso in modo che non riceva i segnali generati dal terminale di controllo.

[modificare]

Assicurati di leggere attentamente la sezione RATIONALE della pagina setpgid . È un po ‘complicato colbind qui tutte le potenziali condizioni di gara.

Per garantire al 100% che nessun SIGINT sarà consegnato al tuo processo figlio, devi fare qualcosa del genere:

 #define CHECK(x) if(!(x)) { perror(#x " failed"); abort(); /* or whatever */ } /* Block SIGINT. */ sigset_t mask, omask; sigemptyset(&mask); sigaddset(&mask, SIGINT); CHECK(sigprocmask(SIG_BLOCK, &mask, &omask) == 0); /* Spawn child. */ pid_t child_pid = fork(); CHECK(child_pid >= 0); if (child_pid == 0) { /* Child */ CHECK(setpgid(0, 0) == 0); execl(...); abort(); } /* Parent */ if (setpgid(child_pid, child_pid) < 0 && errno != EACCES) abort(); /* or whatever */ /* Unblock SIGINT */ CHECK(sigprocmask(SIG_SETMASK, &omask, NULL) == 0); 

A rigor di termini, ognuno di questi passaggi è necessario. Devi bloccare il segnale nel caso in cui l'utente preme Ctrl-C subito dopo la chiamata al fork . Devi chiamare setpgid nel bambino nel caso in cui l' execl avvenga prima che il genitore abbia il tempo di fare qualsiasi cosa. Devi chiamare setpgid nel genitore nel caso in cui il genitore setpgid eseguito e qualcuno setpgid Ctrl-C prima che il bambino abbia il tempo di fare qualsiasi cosa.

La sequenza di cui sopra è maldestra, ma gestisce il 100% delle condizioni di gara.

Cosa stai facendo nel tuo gestore? Esistono solo alcune funzioni Qt che è ansible chiamare in modo sicuro da un gestore di segnale unix. Questa pagina nella documentazione identifica quelli che sono.

Il problema principale è che il gestore verrà eseguito al di fuori del thread dell’evento Qt principale. Quella pagina propone anche un metodo per affrontare questo. Preferisco che il gestore “post” un evento personalizzato per l’applicazione e gestirlo in questo modo. Ho pubblicato una risposta che descrive come implementare eventi personalizzati qui .