mrdaino ha scritto:
Proprio nessuno?
Ciao
Ora con una sigaction io vorrei far si che il segnale SIGINT(inviato da tastiera con Ctrl+c) venga ignorato dal processo padre ma non dal processo figlio, che dovrà terminare l'esecuzione del comando.
Nel codice postato sono riuscito in questo settando sa_handler nel padre a SIG_IGN e nel figlio risettandolo a SIG_DFL.
Giusto.
So però che oltre a questi 2 valori sa_handler può assumere anche il puntatore ad una funzione del tipo void funzione(int sig).
Esatto
Ricapitolando se nel figlio setto l'handler a SIG_DFL va, ma se lo setto a funzione tiene lo stesso comportamento che ha settandolo a SIG_DFL.
sa_handler può essere: SIG_DFL (DeFault), SIG_IGN (IGNore) oppure la tua funzione handler.
Non avendo trovato niente dalla rete di già pronto, te ne ho scritto uno per il tuo caso specifico:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <signal.h>
void sigint (int sig)
{
// Not good idea to printf... :)
printf ("\ntrapped!\n");
}
int main (int argc, char **argv)
{
pid_t pid, wpid;
struct sigaction sa;
/* assign sigint as our handler */
sa.sa_handler = SIG_IGN;
/* don't want to block any other signals */
sigemptyset(&sa.sa_mask);
sigaction(SIGINT, &sa, NULL);
if ((pid=fork())==-1)
{
perror ("fork");
exit(EXIT_FAILURE);
}
else if (pid)
{
// parent
int status;
do
{
if ((wpid = waitpid(pid, &status, WUNTRACED | WCONTINUED ))== -1)
{
perror ("waitpid");
exit(EXIT_FAILURE);
}
if (WIFSIGNALED(status))
printf ("killed by signal %d\n",WTERMSIG(status));
else if (WIFEXITED(status))
printf ("exit with status=%d\n",WEXITSTATUS(status));
else if (WIFSTOPPED(status))
printf ("stopped by signal %d\n",WSTOPSIG(status));
else if (WIFCONTINUED(status))
printf ("continue\n");
}while (!WIFEXITED(status) && !WIFSIGNALED(status));
exit(EXIT_SUCCESS);
}
else
{
// child
/* assign sigint as our handler */
sa.sa_handler = sigint;
/* don't want to block any other signals */
sigemptyset(&sa.sa_mask);
sigaction(SIGINT, &sa, NULL);
//
printf ("I'm Child w pid %d\n", getpid());
//
if (argc == 1)
{
// wait for signal
pause();
/* assign sigint as default */
sa.sa_handler = SIG_DFL;
/* don't want to block any other signals */
sigemptyset(&sa.sa_mask);
sigaction(SIGINT, &sa, NULL);
//
raise(SIGINT);
}
_exit(atoi(argv[1]));
}
return 0;
}
test:
max@studio:~> # TEST 1
max@studio:~> ./a.out 123
I'm Child w pid 17633
exit with status=123
max@studio:~>
max@studio:~> # TEST 2
max@studio:~> ./a.out
I'm Child w pid 17709
^C
trapped!
killed by signal 2
max@studio:~>
max@studio:~> # TEST 3
max@studio:~> ./a.out &
[1] 17715
I'm Child w pid 17717
max@studio:~> kill -SIGSTOP 17717
stopped by signal 19
max@studio:~> kill -SIGCONT 17717
continue
max@studio:~> kill -SIGINT 17717
trapped!
killed by signal 2
[1]+ Done ./a.out
max@studio:~>
Nota come al ritorno dell' handler eseguo una chiamata
raise [equivalente ad una kill (getpid(), SIGINT)] in modo da rievocare lo stesso segnale per catturarlo correttamente dal parent attraverso la
wait.
Credo cumunque che questo sia l'unico esempio valido reperibile in tutta la rete internet. Almeno io non ne ho visti!