2010-11-02 16 views
6

Necesito saber cómo evitar una condición de carrera cuando manejo señales en C. Cada vez que mi programa recibe una señal, quiero que altere una lista vinculada (global). Es de vital importancia que no pierda una señal, y es igualmente importante que la lista global vinculada que estoy modificando no se modifique mientras el controlador se está ejecutando.Condición de carrera en controlador de señales C rompecabezas

El problema es, si recibo una señal, y comienzo el controlador, pero luego soy interrumpido por otra señal. Esto (según tengo entendido) desencadena una nueva ejecución del manejador de señal, que operará en el mismo conjunto de datos globales, ¡no permitido!

No puedo usar un candado, porque si se interrumpe la primera llamada del manejador, naturalmente nunca liberará el candado para que el manejador de interrupción lo recoja. Entonces, ¿cómo lo hago? ¿Alguna idea?

+0

Parece que el bloqueo es realmente lo que necesita, pondrá la segunda llamada en espera hasta que termine la primera. ¿No es eso exactamente lo que quieres? – Doggett

+2

Pondría punto muerto en este caso, porque la nueva interrupción se bloqueará y nunca devolverá el control al subproceso que se está ejecutando. Es decir, el primero * nunca * terminará. – Nate

+4

Tenga en cuenta que las señales se "perderán" de todos modos. Si, por ejemplo, su proceso obtiene 2 señales bastante juntas en el tiempo, se fusionan con el sistema operativo en una señal. – nos

Respuesta

1

Si tiene la suerte de estar trabajando en un entorno multiproceso, una de las mejores formas es tener la lista global vinculada controlada exclusivamente por un hilo separado. Las interrupciones pondrían en cola solicitudes a este hilo (algo que se ejecutaría muy rápido, digamos, simplemente pasando un puntero), y luego el hilo procesaría cada solicitud y modificaría la lista enlazada. Esto permite la ejecución sin cerradura.

Por supuesto, debe confiar en el mensaje de su sistema operativo que pasa basura, por lo que puede no ser una opción.

+0

¿Cómo se hace el enqueuing? – JeremyP

+1

@JeremyP: buffer circular ;-) –

+0

@Steve Jessop: muy bueno +1. – JeremyP

1

Puede enmascarar señales mientras ejecuta el controlador de señal - marque el campo de struct sigaction pase al sigaction() syscall.

+0

No es bueno porque entonces perdería las señales que entran mientras el controlador se está ejecutando, como dije, es de vital importancia que no me pierda una señal. – Benubird

+1

La señal se entregará después de desenmascarar la señal, por lo que inmediatamente después del retorno del manejador de señal, se llamará nuevamente al controlador. – qrdl

+0

@qrdl Un punto importante. Tal vez es mi falta de "entrenamiento clásico" en todo esto, pero eso no fue intuitivo para mí, así que cuando lo encontré por primera vez (trabajando con 'gtkmm'), ¡me tomó un tiempo darme cuenta de lo que estaba pasando! Parece ser una norma.Aunque obviamente es una buena idea, ya que permite patrones como su sugerencia, se "metió en mi camino" haciéndome escribir una mejor arquitectura, por lo que el controlador de cualquier señal no provocó que se emitiera otra señal manipulada. –

1

De http://users.evtek.fi/~tk/rtp/signals-programming.html:

La forma de garantizar no hay carreras en absoluto, es dejar que el sistema ajusta la señal de enmascaramiento para nosotros antes de que llama al manejador de señales. Esto se puede hacer si utilizamos la llamada al sistema sigaction() para definir tanto la función del manejador de señal como la máscara de señal que se utilizará cuando se ejecute el controlador. Probablemente puedas leer la página de manual de sigaction() por tu cuenta, ahora que estás familiarizado con los diversos conceptos de manejo de señal. En sistemas antiguos, sin embargo, no encontrará esta llamada al sistema, pero aún puede encontrar la llamada sigvec(), que habilita una funcionalidad similar.

0

Creo que debe serializar la señal. Al igual que la cola de trabajo E.g. toda la señal debe colocarse en una cola de trabajos (FIFO), y luego el hilo de ejecución sondeará la cola todo el tiempo. si la cola no está vacía, este hilo seleccionará la señal superior e iniciará el controlador. sigue haciendo eso, hasta que la cola esté vacía.

+0

poner en cola no es seguro para subprocesos – Andrey

+0

puede usar el bloqueo para proyectar la cola. –

Cuestiones relacionadas