¿Cómo se consulta un pthread para ver si aún se está ejecutando?

En mi destructor quiero destruir un hilo limpiamente.

Mi objective es esperar a que un hilo termine de ejecutarse y LUEGO destruir el hilo.

Lo único que encontré sobre la consulta del estado de un pthread es pthread_attr_setdetachstate, pero esto solo te dice si tu hilo es:

  • PTHREAD_CREATE_DETACHED
  • PTHREAD_CREATE_JOINABLE

Ambas cosas no tienen nada que ver con si el hilo aún se está ejecutando o no.

¿Cómo se consulta un pthread para ver si aún se está ejecutando?

Parece que tienes dos preguntas aquí:

¿Cómo puedo esperar hasta que mi hilo termine?

Respuesta: Esto es soportado directamente por pthreads – haga que su thread-to-be-stopped sea JOINABLE (cuando se inicia por primera vez), y use pthread_join () para bloquear su hilo actual hasta que el thread-to-be-stopped deje de serlo corriendo.


¿Cómo puedo saber si mi hilo todavía se está ejecutando?

Respuesta: Puedes agregar una bandera “thread_complete” para hacer el truco:

Escenario: el subproceso A quiere saber si el subproceso B aún está activo.

Cuando se crea el hilo B, se le da un puntero a la dirección del indicador “thread_complete”. El indicador “thread_complete” debe inicializarse en NOT_COMPLETED antes de que se cree el subproceso. La función de punto de entrada del subproceso B debe llamar inmediatamente a pthread_cleanup_push () para enviar un “controlador de limpieza” que establece el indicador “thread_complete” en COMPLETED.

Vea los detalles sobre los manejadores de limpieza aquí: manejadores de limpieza pthread

Deberá incluir una llamada pthread_cleanup_pop (1) correspondiente para asegurarse de que se llama al controlador de limpieza sin importar qué (es decir, si el hilo sale normalmente O debido a una cancelación, etc.).

Entonces, el hilo A simplemente puede verificar el indicador “thread_complete” para ver si el hilo B ya salió.

NOTA: Su indicador “thread_complete” debe declararse “volátil” y debe ser de tipo atómico; los comstackdores de GNU proporcionan el sig_atomic_t para este propósito. Esto permite que los dos hilos consigan acceso a los mismos datos sin la necesidad de construcciones de sincronización (mutexes / semáforos).

pthread_kill(tid, 0); 

No se envía ninguna señal, pero la comprobación de errores aún se realiza para que pueda usar eso para verificar la existencia de tid.

PRECAUCIÓN : esta respuesta es incorrecta. El estándar específicamente prohíbe pasar el ID de un hilo cuya vida ha terminado. Esa ID ahora podría especificar un hilo diferente o, peor aún, podría referirse a la memoria que se ha liberado, causando un locking.

Creo que todo lo que realmente necesitas es llamar a pthread_join (). Esa llamada no volverá hasta que el hilo haya salido.

Si solo desea sondear para ver si el hilo aún se está ejecutando o no (y tenga en cuenta que generalmente no es lo que debería querer hacer), podría hacer que el hilo establezca un booleano volátil en falso justo antes de que salga. Luego, su hilo principal podría leer el booleano y, si sigue siendo cierto, sabrá que el hilo aún se está ejecutando. (Si es falso, por otro lado, usted sabe que el hilo al menos casi se ha ido, puede seguir ejecutando el código de limpieza que ocurre después de que establece booleano en falso, así que incluso en este caso, debe llamar a pthread_join antes tratando de liberar cualquier recurso al que el hilo pueda tener acceso)

No hay una solución totalmente portátil, fíjate si tu plataforma admite pthread_tryjoin_np o pthread_timedjoin_np. Así que solo verifica si se puede unir el hilo (por supuesto creado con PTHREAD_CREATE_JOINABLE).

Permítanme señalar la respuesta “ganadora”, que tiene un gran defecto oculto, y en algunos contextos puede provocar lockings. A menos que use pthread_join, aparecerá una y otra vez. Supongamos que está teniendo un proceso y una biblioteca compartida. Llame a la biblioteca lib.so.

  1. Lo dlopen, comienzas un hilo en él. Supongamos que no quiere que se una a él, por lo que lo establece de forma desmontable.
  2. Proceso y lógica de lib compartida haciendo su trabajo, etc.
  3. Desea cargar lib.so, porque ya no lo necesita.
  4. Llamas a un cierre en el hilo y dices, que quieres leer una bandera después del hilo de tu lib.so, que ha terminado.
  5. Continúa en otro hilo con dlclose, porque ves, que has visto, que la bandera ahora muestra el hilo como “terminado”
  6. dlclose cargará toda la stack y la memoria relacionada con el código.
  7. Whops, pero dlclose no detiene los hilos. Y ya sabes, incluso cuando estás en la última línea del controlador de limpieza para configurar la variable de indicador atómico volátil “thread is finished”, todavía tienes que volver de muchos métodos en la stack, devolviendo valores, etc. se le dio una prioridad de subproceso enorme al subproceso # 5 + # 6, recibirá un archivo adjunto antes de que pueda REALMENTE detenerse en el subproceso. A veces tendrás algunos accidentes agradables.

Permítanme señalar que este no es un problema hipotético, tuve el mismo problema en nuestro proyecto.

 #include  #include  #include  #include  #include  void* thread1 (void* arg); void* thread2 (void* arg); int main() { pthread_t thr_id; pthread_create(&thr_id, NULL, thread1, NULL); sleep(10); } void* thread1 (void* arg) { pthread_t thr_id = 0; pthread_create(&thr_id, NULL, thread2, NULL); sleep(5); int ret = 0; if( (ret = pthread_kill(thr_id, 0)) == 0) { printf("still running\n"); pthread_join(thr_id, NULL); } else { printf("RIP Thread = %d\n",ret); } } void* thread2 (void* arg) { // sleep(5); printf("I am done\n"); }