2012-07-26 13 views
87

En Linux, ¿qué sucede cuando un programa (que posiblemente tiene varios hilos) recibe una señal, como SIGTERM o SIGHUP?Gestión de señales con varios hilos en Linux

¿Qué hilo intercepta la señal? ¿Pueden varios hilos obtener la misma señal? ¿Hay un hilo especial dedicado exclusivamente al manejo de señales? Si no, ¿qué sucede dentro del hilo que debe manejar la señal? ¿Cómo se reanuda la ejecución después de que finaliza la rutina del manejador de señal?

Respuesta

30

Esto se matiza ligeramente, según la versión del kernel de Linux que esté utilizando.

Suponiendo 2.6 subprocesos de posix, y si está hablando del sistema operativo que envía SIGTERM o SIGHUP, la señal se envía al proceso, que es recibido y manejado por el subproceso raíz. Usando hilos POSIX, también puede enviar SIGTERM a hilos individuales, pero sospecho que está preguntando qué sucede cuando el sistema operativo envía la señal al proceso.

En 2.6, SIGTERM hará que los subprocesos hijos salgan "limpiamente", donde como 2.4, los subprocesos secundarios quedaron en un estado indeterminado.

+0

y lo que sucede en el interior del hilo de la raíz cuando se recibe una señal? Digamos que escribí un controlador de señal personalizado para SIGUSR1, y ahora estoy enviando esa señal al proceso. El hilo raíz obtendrá esa señal. Quizás está en el medio de alguna función en ese momento. Que es lo que va a pasar? –

+1

si tiene una configuración de controlador, se tratará como una interrupción y el flujo del programa se detendrá y se ejecutará su controlador personalizado. Una vez que se haya ejecutado, el control volverá, asumiendo que no ha hecho nada para alterar el flujo normal (salir, etc.). – Alan

+0

Tenga en cuenta que esto es específico de SIGUSR1, que IIRC no interrumpe las llamadas al sistema. Si ha intentado esto con SIGINT, por ejemplo, podría interrumpir la lectura de una secuencia, y cuando haya regresado para leer, la secuencia puede devolver un error que fue interrumpido. – Alan

102

pthreads(7) describe que POSIX.1 requiere que todos los hilos en una atributos comparten proceso, incluyendo:

  • disposiciones de señal

POSIX.1 también requiere algunos atributos para ser distinta para cada hilo , incluyendo:

  • máscara de señal (pthread_sigmask(3))

  • pila alternativa de señales (de rutina sigaltstack(2))

del núcleo de Linux complete_signal() tiene el siguiente bloque de código - los comentarios son muy útiles:

/* 
    * Now find a thread we can wake up to take the signal off the queue. 
    * 
    * If the main thread wants the signal, it gets first crack. 
    * Probably the least surprising to the average bear. 
    */ 
    if (wants_signal(sig, p)) 
      t = p; 
    else if (!group || thread_group_empty(p)) 
      /* 
      * There is just one thread and it does not need to be woken. 
      * It will dequeue unblocked signals before it runs again. 
      */ 
      return; 
    else { 
      /* 
      * Otherwise try to find a suitable thread. 
      */ 
      t = signal->curr_target; 
      while (!wants_signal(sig, t)) { 
        t = next_thread(t); 
        if (t == signal->curr_target) 
          /* 
          * No thread needs to be woken. 
          * Any eligible threads will see 
          * the signal in the queue soon. 
          */ 
          return; 
      } 
      signal->curr_target = t; 
    } 

    /* 
    * Found a killable thread. If the signal will be fatal, 
    * then start taking the whole group down immediately. 
    */ 
    if (sig_fatal(p, sig) && 
     !(signal->flags & (SIGNAL_UNKILLABLE | SIGNAL_GROUP_EXIT)) && 
     !sigismember(&t->real_blocked, sig) && 
     (sig == SIGKILL || !t->ptrace)) { 
      /* 
      * This signal will be fatal to the whole group. 
      */ 

Por lo tanto, se ve que usted están a cargo de donde se entregan las señales:

Si su proceso ha establecido una disposición de señal a SIG_IGN o SIG_DFL, luego se ignora la señal (o por defecto - kill, core o ignore) para todos los hilos.

Si su proceso ha establecido una disposición de señal para una rutina de controlador específica, entonces puede controlar qué hilo recibirá las señales manipulando máscaras de señal de hilo específicas usando pthread_sigmask(3). Puede nominar un hilo para gestionarlos todos, o crear un hilo por señal, o cualquier combinación de estas opciones para señales específicas, o puede confiar en el comportamiento predeterminado actual del kernel de Linux de entregar la señal al hilo principal.

Algunas señales, sin embargo, son especiales:

A signal may be generated (and thus pending) for a process as 
    a whole (e.g., when sent using kill(2)) or for a specific 
    thread (e.g., certain signals, such as SIGSEGV and SIGFPE, 
    generated as a consequence of executing a specific machine- 
    language instruction are thread directed, as are signals 
    targeted at a specific thread using pthread_kill(3)). A 
    process-directed signal may be delivered to any one of the 
    threads that does not currently have the signal blocked. If 
    more than one of the threads has the signal unblocked, then 
    the kernel chooses an arbitrary thread to which to deliver 
    the signal. 
+6

¡Gracias por tomarse la molestia de extraer el código del kernel! muy útil. – cheshirekow

Cuestiones relacionadas