Como @sarnold señaló, por defecto el hilo no se puede cancelar con pthread_cancel()
sin llamar a cualquiera de las funciones que son puntos de cancelación ... pero esto puede cambiarse utilizando pthread_setcanceltype()
para establecer el tipo de cancelación de la secuencia en asíncrona en lugar de diferida. Para hacer eso, agregaría algo como pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS,NULL);
cerca del inicio de su función de hilo, antes de comenzar el ciclo. A continuación, podrá finalizar el hilo llamando al pthread_cancel(th)
desde main()
.
Tenga en cuenta, sin embargo, que las discusiones cancelación de esta manera (ya sea asíncrona o no) no limpiar los recursos asignados en la función de hilo (como se ha señalado por Kevin en un comentario). Con el fin de hacer esto limpiamente, es posible:
- Asegúrese de que el hilo no hace nada tiene que limpiar antes de la salida (por ejemplo, utilizando
malloc()
asignar un búfer)
- Asegúrese de que tiene alguna forma de limpieza después de la rosca en otro lugar, después de que el hilo sale
pthread_cleanup_push()
uso y pthread_cleanup_pop()
a agregar controladores de limpieza para limpiar los recursos cuando el hilo se cancela. Tenga en cuenta que esto sigue siendo riesgoso si el tipo de cancelación es asincrónico, ya que el hilo podría cancelarse entre la asignación de un recurso y la adición del controlador de limpieza.
- Evitar el uso de
pthread_cancel()
y tienen el hilo comprobar alguna condición para determinar cuándo terminar (que se comprueba en los bucles de larga duración). Dado que su hilo luego verifica la finalización en sí mismo, puede hacer cualquier limpieza que necesite después del control.
Una forma de implementar la última opción es utilizar un mutex como bandera, y lo prueba con pthread_mutex_trylock()
envuelto en una función para utilizar en las pruebas de bucle:
#include <pthread.h>
#include <unistd.h>
#include <errno.h>
/* Returns 1 (true) if the mutex is unlocked, which is the
* thread's signal to terminate.
*/
int needQuit(pthread_mutex_t *mtx)
{
switch(pthread_mutex_trylock(mtx)) {
case 0: /* if we got the lock, unlock and return 1 (true) */
pthread_mutex_unlock(mtx);
return 1;
case EBUSY: /* return 0 (false) if the mutex was locked */
return 0;
}
return 1;
}
/* Thread function, containing a loop that's infinite except that it checks for
* termination with needQuit()
*/
void *thread_do(void *arg)
{
pthread_mutex_t *mx = arg;
while(!needQuit(mx)) {}
return NULL;
}
int main(int argc, char *argv[])
{
pthread_t th;
pthread_mutex_t mxq; /* mutex used as quit flag */
/* init and lock the mutex before creating the thread. As long as the
mutex stays locked, the thread should keep running. A pointer to the
mutex is passed as the argument to the thread function. */
pthread_mutex_init(&mxq,NULL);
pthread_mutex_lock(&mxq);
pthread_create(&th,NULL,thread_do,&mxq);
sleep(2);
/* unlock mxq to tell the thread to terminate, then join the thread */
pthread_mutex_unlock(&mxq);
pthread_join(th,NULL);
sleep(2);
return 0;
}
Si el hilo no es separado (por lo general no es por defecto), debe llamar al pthread_join()
después de detener el hilo.Si el hilo está desacoplado, no necesita unirlo, pero no sabrá exactamente cuándo termina (o incluso aproximadamente, a menos que agregue otra forma de indicar su salida).
pthreads Cancelación significa que el hilo no tiene ninguna oportunidad de limpiar cualquier memoria asignó. –
Ok, resolví esto simplemente con un 'keepalive = 1' global. Luego cambié el 'while (1)' a 'while (keepalive)'. Para matar el hilo ahora solo tengo que cambiar el valor de la variable keepalive a 0 y voila! – Pithikos