2011-11-11 26 views
9

Tengo una aplicación principal que genera un hilo separado para procesar mensajes de una cola. Tengo un problema en AIX cuando presiono CTRL-C, ya que parece que algunos "controles de conexión" en el hilo se vuelven inválidos. Tengo un gancho de cierre en el programa principal capturando el SIGINT pero en AIX parece que de alguna manera envía una señal al hilo también ... aunque eso no es realmente posible por lo que escuché ...¿Cómo bloquear todas las SEÑALES en el hilo SIN usar SIGWAIT?

Esencialmente I me gustaría saber si quiero que la aplicación MAIN maneje TODAS las señales que me interesan y que el/los hilo (s) NUNCA manejen ninguna señal ... ¿es esa "buena práctica"?

En caso afirmativo, ¿cómo no puedo utilizar "sigwait" en el hilo ... de hecho, no quiero ningún "código de señal" en el/los hilo/s ... simplemente no deben recibir ninguna señal.

he vaciado todas las señales:

sigemptyset(&set); 

y ha establecido el SIG_BLOCK

s = pthread_sigmask(SIG_BLOCK, &set, NULL); 

Así que aquí es mediante un programa de prueba simulada:

#include <pthread.h> 
#include <stdio.h> 
#include <stdlib.h> 
#include <unistd.h> 
#include <signal.h> 
#include <errno.h> 

#define handle_error_en(en, msg) do { errno = en; perror(msg); exit(EXIT_FAILURE); } while (0) 

static void * threadMainLoop(){ 
    //Here I do not want the thread to use "sigwait".... 
    while(running == TRUE){ 
     //do some thread work and never have any signals come in 
    } 
} 

void shutdownHook(int sig){ 
    printf("\nCtrl-C pressed....shutdown hook in main...\n"); 
} 

void signalErrorHandler(int signum){ 
    printf("\nSignal error handler in main...\n"); 
} 

int main(int argc, char *argv[]){ 
    pthread_t thread; 
    sigset_t set; 
    int s; 

    //Catch the following signals in the MAIN thread 
    (void) signal(SIGINT, shutdownHook); 
    (void) signal(SIGSEGV, signalErrorHandler); 
    (void) signal(SIGBUS, signalErrorHandler); 
    (void) signal(SIGILL, signalErrorHandler); 
    (void) signal(SIGTERM, signalErrorHandler); 
    (void) signal(SIGABRT, signalErrorHandler); 

    sigemptyset(&set); //BLOCK all signals 

    s = pthread_sigmask(SIG_BLOCK, &set, NULL); 
    if (s != 0) 
     handle_error_en(s, "pthread_sigmask"); 

    s = pthread_create(&thread, NULL, &threadMainLoop, (void *) NULL); 
    if (s != 0) 
     handle_error_en(s, "pthread_create"); 

    pause(); 
} 

Si yo acabo de crear un subproceso y tiene, por ejemplo, el manejador de señal SIGINT en el subproceso MAIN, pero NO tiene el SIG_BLOCK establecido para el tercero ad y el usuario pulsa CTRL-C ... ¿se ve afectado el hilo aunque se ejecute el manejador de señal en el hilo principal? Eso parece ser lo que estoy viendo en AIX ;-(

Gracias por la ayuda, muy apreciados

Lynton

Respuesta

13

Con s = pthread_sigmask(SIG_BLOCK, &set, NULL);, no bloquear nada

Uso:.

sigfillset(&set); 
sets = pthread_sigmask(SIG_SETMASK, &set, NULL); 

Si desea bloquear todas las señales, o explícitamente añadir las señales que desea bloquear a la set si está usando SIG_BLOC K.

Después de crear los hilos, es necesario para restaurar la máscara de señales, de lo contrario no hay hilos contraerá ninguna señal.

Sin embargo, mirando a su pregunta anterior, podría ser que el hilo de la captura de la señal no maneja siendo interrumpido. Es decir, si se bloquea haciendo un syscall y llega una señal, ese syscall se cancela. Algunos sistemas operativos predeterminados para llamar automáticamente a la llamada al sistema de nuevo, algunos devuelve un error y establece errno en EINTR, que la aplicación debe manejar, y cosas malas pueden suceder si no se maneja.

En su lugar, instale sus controladores de señal con sigaction() en lugar de señal(), y configure el indicador SA_RESTART, lo que provocará que las llamadas al sistema se reinicien automáticamente en caso de que se anule por una señal.

+0

Hola, pero configuro "s = pthread_sigmask (SIG_BLOCK, & set, NULL);" y prueba con CTRL-C que el hilo no recibe la señal? Eso significa que lo está bloqueando? Si agrego "sigaddset (& set, SIGINT);" entonces el hilo recibe la señal. Perdónenme si me equivoco aquí ... todavía estoy aprendiendo ... ;-) Gracias por la ayuda ;-) –

+0

Actualicé un poco la respuesta. La máscara de señal son las señales que no se pueden elevar. Entonces, si haces sigaddset (& set, SIGINT); pthread_sigmask (SIG_BLOCK, & set, NULL); , SIGINT se establecerá en la máscara individual, y eso significa que el hilo no lo recibirá. Si crea un nuevo subproceso, ese subproceso hereda la máscara de señal del subproceso que lo creó. – nos

+0

Tenga en cuenta que si desea que un nuevo hilo comience con señales enmascaradas (generalmente necesarias para evitar condiciones desagradables) debe bloquear las señales antes de llamar a 'pthread_create' y luego restaurar la vieja máscara de señal en el hilo original después de' pthread_create' . –

-11

Aún mal diseño. No use CTRL + C para detener una aplicación de forma controlada. Utilice una aplicación de controlador correctamente diseñada a la que se pueda acceder a través de CORBA, RMI u otro método para interactuar con el usuario y controlar la aplicación en segundo plano.

Diviértete chicos ...

Cuestiones relacionadas