2010-11-17 31 views
10

Sé cómo enviar señales al proceso hijo en C usando la función kill(pid_t pid, int sig). ¿Qué pasa con el envío de señales a los hilos? ¿Es posible?. Si es así, cómo atrapar señales en el hilo "hijo". Por ejemplo, si el hilo principal me envía una señal de terminación, ¿cómo puedo atraparlo en el otro hilo?Enviar y detectar señales en pthreads en C

Respuesta

8

Con hilos POSIX, tiene las funciones pthread_cond_wait y pthread_cond_signal.

int pthread_cond_wait(pthread_cond_t *restrict cond, pthread_mutex_t *restrict mutex) 
int pthread_cond_signal(pthread_cond_t *cond) 

El señaliza hilo debe bloquear en una llamada pthread_cond_wait hasta que otro hilo envía una señal usando pthread_cond_signal, con la misma condición variable.

Considerando la analogía con las señales entregadas a los procesos, esto es un poco diferente porque el hilo señalado ya ha suspendido su ejecución esperando una señal, a diferencia de un proceso que simplemente se interrumpe y continúa.

+7

Esto es bastante diferente a las señales. Aunque estoy de acuerdo en que esto generalmente es un mejor enfoque, 'pthread_kill' es la respuesta a la pregunta de OP, creo. –

+2

@R ..: En realidad, la pregunta no es muy clara y asumí que el autor no está preguntando sobre la entrega de señales del sistema operativo a un hilo en particular, sino más bien sobre el envío de señales entre hilos. –

0

No estoy seguro de que esto sea posible, ya que depende de la plataforma y la implementación, y sugiero que no use señales para comunicarse entre hilos. A veces, solo un hilo específico recibirá señales y, a veces, todos los hilos recibirán señales.

Existen mejores mecanismos de comunicación de hilos como colas, semáforos y bloqueos.

2

Las señales no tienen afinidad con el hilo. Se manejan completamente de forma asincrónica. Cuando especifica un manejador de señal con signal(2) o sigaction(2), es un manejador de señal global. Cuando se genera una señal, el controlador de señal se ejecuta en la parte superior de la pila de cualquier cadena que se esté ejecutando en ese momento, y usted no puede controlar eso.

Parece que quieres algún otro tipo de comunicación intertrabajo. La forma más sencilla de hacerlo es con una variable compartida volatile:

volatile bool should_terminate = false; 

void ChildThread() 
{ 
    while(!should_terminate) 
    { 
     // do stuff 
    } 
} 

void MainThread() 
{ 
    // To terminate child thread: 
    should_terminate = true; 
} 

Si necesita control de concurrencia más fuerte, mira en exclusiones mutuas variables de condición, y semáforos.

7

Las señales se envían a un proceso como un todo. Cada señal enviada al proceso se recibe por un solo hilo (en nombre de todo el programa). Hay máscaras de señal por hilo que influyen en si un hilo en particular es elegible para manejar una señal particular.

Por lo tanto, necesita un manejador de señal, posiblemente en un solo hilo. Sin embargo, tenga en cuenta que hay límites en lo que se supone que debe hacer en el manejador de señal de un subproceso. Tenga cuidado de alejarse mucho de las promesas hechas por el estándar (que son mínimas).

Sin embargo, la función pthread_kill() se puede utilizar para enviar señales a otros hilos, siempre que el hilo actual puede identificar (tiene acceso a los valores de ID de hilo (pthread_t) que identifican a) los hilos que todavía se están ejecutando dentro del proceso. Puede decidir retransmitir la señal a los otros hilos utilizando un número de señal diferente al capturado originalmente (por lo que un hilo recibe la señal externa, pero muchos hilos reciben la señal interna). O puede usar otra primitiva de sincronización o comunicación Pthread en lugar de señales.

+0

Me gustaría aclarar que "tiene acceso a la identificación del hilo". En términos de corrección formal, incluso si tiene el 'pthread_t' almacenado, no es válido (comportamiento indefinido) para hacer uso de él si el hilo pudo haber terminado en un estado separado o con otro hilo que ya llama' pthread_join' en él. –