Estoy codificando el cierre de un servidor multiproceso, si todo va como debería, todos los subprocesos salen por sí solos, pero hay una pequeña posibilidad de que un subproceso se atasque, en este caso sería conveniente tener una unión sin bloqueo para que yo pudiera hacer.
¿Hay alguna forma de hacer un pthread_join sin bloqueo? Algún tipo de unión programada también sería bueno.
algo como esto:
para cada subproceso hacer nb_pthread_join (); si aún se está ejecutando pthread_cancel ();
Puedo pensar en más casos en los que sería útil una combinación sin bloqueo.
Como parece que no existe tal función, ya he codificado una solución alternativa, pero no es tan simple como me gustaría.
Como otros han señalado, no hay un pthread_join no bloqueante disponible en las bibliotecas pthread estándar.
Sin embargo, dado su problema declarado (tratando de garantizar que todos sus subprocesos hayan salido al cerrar el programa), dicha función no es necesaria. Simplemente puede hacer esto:
int killed_threads = 0;
for(i = 0; i < num_threads; i++) {
int return = pthread_cancel(threads[i]);
if(return != ESRCH)
killed_threads++;
}
if(killed_threads)
printf("%d threads did not shutdown properly\n", killed_threads)
else
printf("All threads exited successfully");
No hay nada de malo en llamar a pthread_cancel en todos sus subprocesos (terminados o no), por lo que llamarlo para todos sus subprocesos no se bloqueará y garantizará la salida del subproceso (limpio o no).
Eso debería calificar como una solución alternativa 'simple'.
Si está ejecutando su aplicación en Linux, es posible que le interese saber que:
int pthread_tryjoin_np(pthread_t thread, void **retval);
int pthread_timedjoin_np(pthread_t thread, void **retval,
const struct timespec *abstime);
Tenga cuidado, como sugiere el sufijo, "np" significa "no portátil". Sin embargo, no son extensiones GNU estándar POSIX, aunque útiles.
El mecanismo 'pthread_join' es una conveniencia para ser utilizado si resulta que hace exactamente lo que desea. No hace nada que no puedas hacer tú mismo y, cuando no sea exactamente lo que quieres, codifica exactamente lo que quieres.
No hay ninguna razón real por la que debas preocuparte si un hilo ha terminado o no. Lo que le importa es si el trabajo que estaba haciendo el hilo está completo. Para decir eso, haga que el hilo haga algo para indicar que está funcionando. La forma de hacerlo depende de lo que sea ideal para su problema específico, que depende en gran medida de lo que estén haciendo los hilos.
Empiece por cambiar su forma de pensar. No es un hilo que se atasca, es lo que estaba haciendo el hilo lo que se atasca.
Si está desarrollando para QNX, puede usar la función pthread_timedjoin ().
De lo contrario, puede crear un subproceso separado que ejecutará pthread_join () y alertará al subproceso principal, al señalar un semáforo, por ejemplo, que el subproceso secundario se completa. Este hilo separado puede devolver lo que se obtiene de pthread_join () para permitir que el hilo principal determine no solo cuándo se completa el hijo, sino también qué valor devuelve.
La respuesta realmente depende de por qué quiere hacer esto. Si solo desea limpiar subprocesos muertos, por ejemplo, probablemente sea más fácil tener un subproceso "limpiador de subprocesos inactivos" que se repita y se une.
No estoy seguro de qué quiere decir exactamente, pero supongo que lo que realmente necesita es un mecanismo de espera y notificación.
En resumen, así es como funciona: espera a que una condición se satisfaga con un tiempo de espera. Tu espera terminará si:
Puede tener esto en un bucle y agregar un poco más de inteligencia a su lógica. El mejor recurso que he encontrado para esto relacionado con Pthreads es este tutorial: Programación de subprocesos POSIX ( https://computing.llnl.gov/tutorials/pthreads/ ).
También estoy muy sorprendido de ver que no hay una API para la unión programada en Pthreads.
No hay pthread_join
, pero si está esperando otro hilo bloqueado por condiciones, puede usar temporizado pthread_cond_timed_wait
en vez de pthread_cond_wait
Puede insertar un byte en una tubería abierta como no bloqueante para señalar al otro subproceso cuando esté listo, luego usar una lectura sin bloqueo para verificar el estado de la tubería.