2009-05-27 19 views
6

Estoy escribiendo un programa, con un hilo maestro y algunos hilos de trabajo, y me gustaría obtener el manejo de la señal correcta. Mi problema es el siguiente:hilos maestro/trabajador y manejo de señales

inicios de rosca Maestro y hacer toda la asignación

hilo Maestro establece un manejador de señales SIGINT

hilos Master Inicio subprocesos de trabajo. los hilos de trabajo no necesitan una limpieza especial, sin embargo, pueden estar durmiendo en la llamada al sistema o en el semáforo.

Cuando se recibe SIGINT, entiendo que solo lo recibe un hilo. Así que si el hilo está durmiendo en la llamada al sistema o en el semáforo, no se despertarán, y no podré pthread_unirme a mis hilos de trabajo y hacer toda la limpieza necesaria en mi hilo maestro.

¿Puede el siguiente controlador de señal resolver mi problema?

void term(int sig) 
{ 
    g_do_cleanup = 1; 
    pthread_kill(worker_1_id, some_other_signal); 
    ... 
    pthread_kill(worker_2_id, some_other_signal); 
} 

Lo que espero es que al recibir SIGINT, todo el hilo se señalizará con otra señal, salir de su llamada de bloqueo, ver la bandera g_do_cleanup y con gracia salida.

Cualquier comentario o enlace sobre cómo hacer esto correctamente es bienvenido.

Edit: No estoy buscando una manera de activar el hilo múltiple en espera de una condición en particular, por lo que no creo que el enfoque pthread_cond_signal es lo que estoy buscando. Lo que quiero es:

  • encontrar un camino que todo hilo que sean bloqueado en una llamada de bloqueo vuelve de estas llamadas.
  • O elimine todos los hilos excepto el principal.

Respuesta

4

Esto es lo que suele hacer en el hilo principal aplicación:


/* before starting other threads */ 
sigset_t sigs; 
sigemptyset(&sigs); 
sigaddset(&sigs, SIGTERM); 
sigaddset(&sigs, SIGINT); 
/* add other signals to handle */ 
if (pthread_sigmask(SIG_BLOCK, &sigs, 0)) { /* handle error */ } 
/* can start threads now */ 
... 
/* in the main event loop */ 
siginfo_t info; 
if (sigwaitinfo(&sigs, &info) == -1) { /* handle error */ } 
switch(info.si_signo) 
{ 
    case SIGTERM: 
    case SIGINT: /* raise shutdown event */ break; 
    default: /* other actions - log rotation, etc. */ 
} 
... 

De esta manera se convierten en señales de eventos de aplicación regulares - no hay restricciones de contexto señal especial, etc. de espera también se podría hacer con un tiempo de espera a través de sigtimedwait , aunque los derivados de BSD no lo admiten.

2

Me parece que lo que quiere es una variable de condición pthread, por lo que puede reactivar cualquier número de subprocesos múltiples cantando un "evento" desde su hilo maestro.

Consulte las páginas man para PTHREAD_COND_DESTROY y PTHREAD_COND_BROADCAST para obtener más información.

+0

Sí.La mayoría de las personas usa pthread o las implementaciones de Win32/MFC para hacer subprocesos – Kieveli

+0

No, no creo que esté bien, porque no me despertaba de una llamada de selección de bloqueo o una llamada sem_wait. Tal vez podría reemplazar mis semáforos por pthread_condition, pero la abstracción de semáforos realmente se ajusta a mi modelo de sincronización. – shodanex

1

Su plan parece estar bien. Está forzando un hilo para manejar las señales del sistema. Deberás enmascarar las señales excepto alguna otra señal en tus hilos de trabajo con pthread-sigmask().

Creo que me gustaría ir con un hilo separado para manejar la señal de proceso en lugar de maestro. Hazlo esperar para siempre en un semáforo o sigwait() o lo que sea mientras esperas ejecutar el controlador de señal. Mueva el código pthread-kill fuera del controlador de señal. Simplemente configure el interruptor y haga que el hilo de señal de espera envíe la otra_señales a los hilos de trabajo y salga por sí mismo.

+0

Usar señales para comunicarse entre hilos es el enfoque equivocado. muchas bibliotecas de hilos ni siquiera funcionan con señales. Es mucho mejor utilizar los mecanismos de sincronización de la banda de rodadura provistos por la biblioteca de hilos como las variables de condición mencionadas. – lothar

+0

Las señales son primitivas y están lejos de ser ideales, pero su biblioteca obviamente las admite o no las estaría preguntando. No está haciendo nada que no se haya hecho con éxito muchas veces. – Duck

+0

Esto no tiene que ver con la comunicación de subprocesos, sino con la terminación de subprocesos. pthread_cancel + un hilo de manejo de señal podría funcionar – shodanex