shatzy
28-11-2012, 21:54
Salve a tutti,
vorrei proporvi questo problema: ho scritto un piccolo esempio di processo multitrhead per capire meglio come funziona la gestione dei thread in linux e in particolare dei segnali.
Vi descrivo brevemente a parole cosa fa il programma:
ho una variabile globale "fine" inizializzata a 0 che indica lo stato di terminazione del sistema.
Il main istalla un handler per i segnali SIGINT e SIGTERM (l'handler setta fine a 1).
Subito dopo crea 3 thread, rispettivamente thread1, thread2, thread3 ed entra in un while(!fine) in cui fa una sleep.
Thread1 e thread2 entrano in un while(!fine) nel quale fanno una semplice fprintf.
Thread1 entra nel while(!fine) fa una sleep(10) al termine della quale manda kill(get(pid),SIGINT).
Il comportamento che mi aspetto è questo:
una volta che thread1 manda kill viene generata SIGINT che è indirizzata al processo stesso, quindi arriverà ad un thread a caso(?).
Dunque partirà l'handler che setta fine=1 e tutti i processi possono uscire dal while e terminare. Il main prima di terminare attende le join per i 3 threads.
Il comportamento che ottengo, invece, è che thread1 appena fatta la kill rientra nel while ancora una volta e fa un ultimo ciclo inviando anche un'altra kill.
Il codice è il seguente:
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <pthread.h>
#include <signal.h>
#include <sys/syscall.h>
volatile sig_atomic_t fine = 0;
pthread_t tid1,tid2,tid3;
/* gestore per SIGINT e SIGTERM */
static void handler (int signum) {
int tid;
tid = syscall (SYS_gettid);
fprintf (stdout,"tid %d \n", tid);fflush(NULL);
fine = 1;
}
void* thread1()
{
int tid;
tid = syscall (SYS_gettid);
while(!fine)
{
fprintf(stdout,"thread1 %d partito\n",tid);fflush(NULL);
sleep(10);
kill(getpid(),SIGINT);
}
fprintf(stdout,"thread1 termina\n");fflush(NULL);
return (void*) 1;
}
void* thread2()
{
int tid;
tid = syscall (SYS_gettid);
while(!fine)
{
fprintf(stdout,"thread2 %d partito\n",tid);fflush(NULL);
sleep(1);
}
fprintf(stdout,"thread2 termina\n");fflush(NULL);
return (void*) 1;
}
void* thread3()
{
int tid;
tid = syscall (SYS_gettid);
while(!fine)
{
fprintf(stdout,"thread3 %d partito \n",tid);fflush(NULL);
sleep(1);
}
fprintf(stdout,"thread3 termina\n");fflush(NULL);
return (void*) 1;
}
int main()
{
sigset_t set;
struct sigaction sa;
void** status=NULL;
/* maschero tutti i segnali */
sigfillset(&set);
pthread_sigmask(SIG_SETMASK,&set,NULL);
/* installo i gestori */
bzero( &sa, sizeof(sa) );
sa.sa_handler = handler;
sigaction(SIGINT,&sa,NULL);
sigaction(SIGTERM,&sa,NULL);
/* tolgo la maschera */
sigemptyset(&set);
pthread_sigmask(SIG_SETMASK,&set,NULL);
/*creo i threads */
pthread_create(&tid1, NULL, &thread1, NULL);
fprintf(stdout,"main -- creato thread1 \n");fflush(NULL);
sleep(1);
pthread_create(&tid2, NULL, &thread2, NULL);
fprintf(stdout,"main -- creato thread2 \n");fflush(NULL);
sleep(1);
pthread_create(&tid3, NULL, &thread3, NULL);
fprintf(stdout,"main -- creato thread3 \n");fflush(NULL);
sleep(1);
while(!fine)
{
fprintf(stdout,"main while\n");fflush(NULL);
sleep(50);
}
pthread_join(tid1,status);
pthread_join(tid2,status);
pthread_join(tid3,status);
fprintf(stdout,"main termina\n");fflush(NULL);
return 1;
}
Qualcuno sa spiegarmi un possibile motivo?
vorrei proporvi questo problema: ho scritto un piccolo esempio di processo multitrhead per capire meglio come funziona la gestione dei thread in linux e in particolare dei segnali.
Vi descrivo brevemente a parole cosa fa il programma:
ho una variabile globale "fine" inizializzata a 0 che indica lo stato di terminazione del sistema.
Il main istalla un handler per i segnali SIGINT e SIGTERM (l'handler setta fine a 1).
Subito dopo crea 3 thread, rispettivamente thread1, thread2, thread3 ed entra in un while(!fine) in cui fa una sleep.
Thread1 e thread2 entrano in un while(!fine) nel quale fanno una semplice fprintf.
Thread1 entra nel while(!fine) fa una sleep(10) al termine della quale manda kill(get(pid),SIGINT).
Il comportamento che mi aspetto è questo:
una volta che thread1 manda kill viene generata SIGINT che è indirizzata al processo stesso, quindi arriverà ad un thread a caso(?).
Dunque partirà l'handler che setta fine=1 e tutti i processi possono uscire dal while e terminare. Il main prima di terminare attende le join per i 3 threads.
Il comportamento che ottengo, invece, è che thread1 appena fatta la kill rientra nel while ancora una volta e fa un ultimo ciclo inviando anche un'altra kill.
Il codice è il seguente:
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <pthread.h>
#include <signal.h>
#include <sys/syscall.h>
volatile sig_atomic_t fine = 0;
pthread_t tid1,tid2,tid3;
/* gestore per SIGINT e SIGTERM */
static void handler (int signum) {
int tid;
tid = syscall (SYS_gettid);
fprintf (stdout,"tid %d \n", tid);fflush(NULL);
fine = 1;
}
void* thread1()
{
int tid;
tid = syscall (SYS_gettid);
while(!fine)
{
fprintf(stdout,"thread1 %d partito\n",tid);fflush(NULL);
sleep(10);
kill(getpid(),SIGINT);
}
fprintf(stdout,"thread1 termina\n");fflush(NULL);
return (void*) 1;
}
void* thread2()
{
int tid;
tid = syscall (SYS_gettid);
while(!fine)
{
fprintf(stdout,"thread2 %d partito\n",tid);fflush(NULL);
sleep(1);
}
fprintf(stdout,"thread2 termina\n");fflush(NULL);
return (void*) 1;
}
void* thread3()
{
int tid;
tid = syscall (SYS_gettid);
while(!fine)
{
fprintf(stdout,"thread3 %d partito \n",tid);fflush(NULL);
sleep(1);
}
fprintf(stdout,"thread3 termina\n");fflush(NULL);
return (void*) 1;
}
int main()
{
sigset_t set;
struct sigaction sa;
void** status=NULL;
/* maschero tutti i segnali */
sigfillset(&set);
pthread_sigmask(SIG_SETMASK,&set,NULL);
/* installo i gestori */
bzero( &sa, sizeof(sa) );
sa.sa_handler = handler;
sigaction(SIGINT,&sa,NULL);
sigaction(SIGTERM,&sa,NULL);
/* tolgo la maschera */
sigemptyset(&set);
pthread_sigmask(SIG_SETMASK,&set,NULL);
/*creo i threads */
pthread_create(&tid1, NULL, &thread1, NULL);
fprintf(stdout,"main -- creato thread1 \n");fflush(NULL);
sleep(1);
pthread_create(&tid2, NULL, &thread2, NULL);
fprintf(stdout,"main -- creato thread2 \n");fflush(NULL);
sleep(1);
pthread_create(&tid3, NULL, &thread3, NULL);
fprintf(stdout,"main -- creato thread3 \n");fflush(NULL);
sleep(1);
while(!fine)
{
fprintf(stdout,"main while\n");fflush(NULL);
sleep(50);
}
pthread_join(tid1,status);
pthread_join(tid2,status);
pthread_join(tid3,status);
fprintf(stdout,"main termina\n");fflush(NULL);
return 1;
}
Qualcuno sa spiegarmi un possibile motivo?