2012-01-29 7 views
5

En mi aplicación, el hilo principal crea dos hilos unidos; uno que espera la entrada del usuario llamando a scanf() en un bucle y otro que escucha las conexiones entrantes del socket llamando a accept() en un bucle. Las nuevas conexiones se manejan en hilos separados que están separados.Interrupción de dos pthreads de bloqueo mediante señales

Quiero que el programa se cierre correctamente cuando se recibe una señal SIGINT. Eso significa que el hilo de escucha debería dejar de aceptar nuevas conexiones, esperar a que los hilos que actualmente sirven a las conexiones se cierren y luego. El hilo que espera la entrada del usuario también debe finalizar y, por lo tanto, permite que termine el hilo principal.

Scanf() y accept() bloquean pero pueden ser interrumpidos por una señal, sin embargo, las señales enviadas al proceso solo pueden ser manejadas por un hilo (AFAIK). Mi idea es bloquear las señales de SIGINT en todos los hilos, excepto en el hilo principal que lo esperará. Cuando recibe un SIGINT, enviará SIGUSR1 a los dos hilos (uno que bloquea en scanf() y otro que bloquea en accept()) y luego se une a estos hilos.

¿Es esta una buena solución? ¿Hay una forma mejor o quizás estándar para lograr esto?

Respuesta

5

La solución canónica para problemas como este es Thread Cancellation. Una solicitud de cancelación que llegue mientras se bloquea un hilo en una función que es un punto de cancelación se tomará de inmediato; de lo contrario, se aplicará la próxima vez que el hilo invoque una función que sea un punto de cancelación.

Lo único que puede ser doloroso al usar la cancelación es que está basado en un modelo de manejo de excepciones en lugar de devoluciones fallidas. Debe mantener la cancelación bloqueada la mayor parte del tiempo (y solo habilitarla durante las operaciones durante las cuales desee manejar la cancelación) o bien instalar controladores de limpieza de cancelación (básicamente, manejadores de excepciones semi-feos en C) en cada nivel de marco de llamada donde podría tener estado intermedio/asignaciones/etc. para borrar cuando se cancela su hilo. Personalmente, prefiero el primer enfoque, que generalmente solo requiere la instalación de controladores de cancelación.

Cualquier aproximación basada en la interrupción de las señales inherentemente tiene condiciones de carrera. Si la señal se envía justo antes de que se llame a la función de bloqueo, cuando el controlador de señal regrese, se llamará a la función de bloqueo y se bloqueará indefinidamente (ya que la verificación de "¿es hora de salir?" Ya se aprobó con éxito).

+0

Gracias - ¡Esperaba en secreto que respondiera esta pregunta! El problema es que, una vez que se cancela un hilo, por ejemplo cuando se bloquea en accept(), no se ejecuta ninguna lógica que lo siga. Necesito que el hilo espere los hilos sueltos que manejan las conexiones y luego libere los recursos antes de que salga. ¿Cómo podría lograr esto? – SlappyTheFish

+0

ah, ¿es pthread_cleanup_push() lo que quería decir con los manejadores de limpieza? Parece que hará el truco. – SlappyTheFish

+0

Sí, así es como usa la cancelación. –

Cuestiones relacionadas