2011-07-10 9 views
5
// threadA.c 
int main() { 
    int res; 
    pthread_t a_thread; 
    void *thread_result; 

    res = pthread_create(&a_thread, NULL, thread_function, NULL); 
    if (res != 0) { 
     perror("Thread creation failed"); 
     exit(EXIT_FAILURE); 
    } 
    sleep(3); 
    printf("Canceling thread...\n"); 
    res = pthread_cancel(a_thread); 
    if (res != 0) { 
     perror("Thread cancelation failed"); 
     exit(EXIT_FAILURE); 
    } 
    printf("Waiting for thread to finish...\n"); 
    res = pthread_join(a_thread, &thread_result); 
    if (res != 0) { 
     perror("Thread join failed"); 
     exit(EXIT_FAILURE); 
    } 
    exit(EXIT_SUCCESS); 
} 

void *thread_function(void *arg) { 
    int i, res, j; 
    res = pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL); 
    if (res != 0) { 
     perror("Thread pthread_setcancelstate failed"); 
     exit(EXIT_FAILURE); 
    } 
    res = pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL); 
    if (res != 0) { 
     perror("Thread pthread_setcanceltype failed"); 
     exit(EXIT_FAILURE); 
    } 
    printf("thread_function is running\n"); 
    for(i = 0; i < 10; i++) { 
     printf("Thread is still running (%d)...\n", i); 
     sleep(1); 
    } 
    pthread_exit(0); 
} 

salida es la siguiente:cómo se cancela el hilo POSIX niño

$ ./threadA 
thread_function is running 
Thread is still running (0)... 
Thread is still running (1)... 
Thread is still running (2)... 
Canceling thread... 
Waiting for thread to finish... 
$ 

Al terminar de esperar 3 segundos, el hilo principal emite el pthread_cancel comando para detener el hilo hijo y el hilo niño realmente comienza a Responda la cancelación después de invocar el comando pthread_join.

Por el momento, el hilo principal corre a la línea inmediatamente después pthread_join, el hilo hijo se está ejecutando dentro del bucle del código siguiente,

for(i = 0; i < 10; i++) { 
     printf("Thread is still running (%d)...\n", i); 
     sleep(1); 
    } 

no veo ninguna declaración de cheques dentro de este bucle , pero el hilo principal todavía puede cancelar el hilo hijo. Supongo que el sistema POSIX multihilo tiene un sistema de verificación interno para que pueda terminar la cadena secundaria cuando se llama pthread_join en la cadena principal.

Pregunta>

Básicamente, lo necesario para comprender cómo el hilo hijo puede ser cancelado dentro del bucle sin que ella misma la comprobación de cualquier indicador.

Además, corrija mi descripción si algo está mal.

Respuesta

6

Lo que sucede es que el bucle contiene al menos un punto de la cancelación, sleep (y posiblemente dos, ya que es un punto printf cancelación opcional).

Ser un punto de cancelación significa que la función contiene una lógica similar a:

if (thread_local_cancellation_flag) { 
    pthread_setcancelstate(PTHREAD_CANCEL_DISABLE); 
    pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED); 
    pthread_exit(PTHREAD_CANCELED); 
} 

En realidad, sin embargo, es un poco más complicado, ya que si la solicitud de cancelación llega mientras la función está "esperando" o " bloqueando "para que ocurra algún evento (como el tiempo de espera para caducar o la entrada de un socket), se debe actuar sobre eso. Por lo tanto, se requiere algún tipo de mecanismo de entrega asincrónico, y la implementación típica es usar señales para esto, pero en realidad es extremadamente difícil hacerlo bien, y las implementaciones populares no funcionan tan bien. Para algunos casos de esquina feas en glibc, que otras implementaciones probablemente comparten, ver este informe de error:

http://sourceware.org/bugzilla/show_bug.cgi?id=12683

En su caso, lo que es casi seguro que está sucediendo es que la solicitud de cancelación llega (a través de una señal), mientras que el hilo es esperando en sleep, y se ejecuta un manejador de señal, determina que está en el medio de una operación cancelable y actúa sobre la solicitud de cancelación.

3

Lea primero la página del manual pthread_cancel. Eso explica mucho. Específicamente a su pregunta, no habrá ninguna declaración de verificación dentro del ciclo. No he comprobado la implementación de Linux, pero lo más racional sería enviar un hilo que solicite una señal para detener/cancelar. Si en el hilo del manejador de señal se determina que es el estado en el que no se puede cancelar, la solicitud se pone en cola. Una vez que llama a cualquier función que sea cancellation point y se determina que el nuevo estado es cancelable, esa cola está marcada y si se encuentra la solicitud de cancelación en la cola, el hilo se cancela. Básicamente, el estado no cancelable es un critical section. En su caso, todos sus hilos se cancelan al llamar al sleep(), ya que es un punto de cancelación. Ver pthreads (7).

+0

'pthread_setcanceltype' y' pthread_setcancelstate' no son puntos de cancelación. El estado de cancelación solo se verifica en los puntos de cancelación, a menos que el tipo de cancelación sea asincrónico, en cuyo caso * MAYO * se puede verificar en otros puntos e interrumpir el código de forma asíncrona (pero no es obligatorio). –

+0

@R ..: Buen punto. Editó la respuesta en consecuencia. Gracias. –

Cuestiones relacionadas