Sto scrivendo un mini-shell (no, non per scuola: P; per il mio divertimento personale) e la maggior parte delle funzionalità di base è stata eseguita ma sono bloccato quando provo a gestire SIGTSTP.blocco waitpid quando non dovrebbe
Presumibilmente, quando un utente preme Ctrl+Z
, SIGTSTP deve essere inviato al processo Foreground della shell se esiste e Shell dovrebbe continuare normalmente.
Dopo la creazione di ogni processo (se si tratta di un processo in primo piano), il seguente codice attende:
if(waitpid(pid, &processReturnStatus, WUNTRACED)>0){//wait stopped too
if(WIFEXITED(processReturnStatus) || WIFSIGNALED(processReturnStatus))
removeFromJobList(pid);
}
E io sto gestendo il segnale come segue:
void sigtstpHandler(int signum)
{
signum++;//Just to remove gcc's warning
pid_t pid = findForegroundProcessID();
if(pid > -1){
kill(-pid, SIGTSTP);//Sending to the whole group
}
}
quello che succede è che quando preme Ctrl+Z
, il processo figlio viene effettivamente sospeso (utilizzando ps -all
per visualizzare lo stato dei processi) ma la mia shell si blocca a waitpid
it neve r restituisce anche se ho passato il flag WUNTRACED
che, per quanto ho capito, dovrebbe restituire waitpid
anche quando il processo viene interrotto.
Quindi cosa avrei potuto fare di sbagliato? o ho capito male il comportamento di waitpid in modo errato?
Note:
-findForegroundProcessID() restituisce il pid corretto; L'ho ricontrollato.
-I sto cambiando il gruppo di ogni processo, quando subito dopo ho fork
-la gestione Ctrl+C
sta lavorando bene
-Se io uso un altro terminale per inviare SIGCONT dopo i miei si blocca di shell, il processo figlio riprende il suo lavoro e il guscio si miete infine.
-Sto catturando SIGTSTP che può essere catturato per quanto ho letto (e testato). -Ho provato ad usare waitid invece di waitpid nel caso in cui il problema persistesse. EDIT:
void sigchldHandler(int signum)
{
signum++;//Just to remove the warning
pid_t pid;
while((pid = waitpid(-1, &processReturnStatus, 0)) > 0){
removeFromJobList(pid);
}
if(errno != ECHILD)
unixError("kill error");
}
mio gestore di SIGCHLD.
IIUC, stai cercando di catturare SIGSTP. Non puoi prendere SIGSTP o SIGKILL. – wildplasser
Non sono sicuro che SIGSTOP sia lo stesso di SIGSTP ma secondo un libro, SIGSTOP non può essere catturato ma SIGTSTP può, in effetti sono sicuro che l'ho preso perché ho stampato qualcosa come test – Fingolfin
Oops, my bad. Se ho letto correttamente, SIGTSTP è stato creato intenzionalmente per consentirne il rilevamento, per consentire al gruppo di processi/al gruppo terminale di propagarlo tra i suoi membri. Se il libro a cui fai riferimento è APERTO, probabilmente sarai in grado di farlo correttamente ... – wildplasser