Actividad

Recuperar el problema de la práctica de la semana 4.

Mientras el programa espera en wait() o waitpid() a que el proceso hijo que ejecuta 'ls' termine, puede llegarle una señal para que termine inmediatamente. Si no manejamos las señales en nuestro programa, el comportamiento por defecto es que el proceso termine, dejando al proceso hijo huérfano. Este continuará su ejecución, si nadie le manda una señal a el para que termine.

Hay muchos motivos por los que nuestro programa puede recibir una señal. Puede que se cierre la terminal, el usuario pulse CTRL-C, se vaya a apagar el sistema o el usuario haya mandado la señal a nuestro proceso directamente, usando el comando 'kill'. En algunos de estos casos, el hijo también recibirá la señal, pero no en todos. Por eso es mejor importante, que si nos han pedido que terminemos y, por tanto, ya no necesitamos la tarea que el proceso hijo estaba realizando, le pidamos que termine y esperemos a que lo haga.

Modifica el programa de la semana 4 para que:

  1. Después de hacer el fork(), en el código ejecutado en el proceso padre, antes del wait(), instale un manejador de señal para señales SIGTERM, SIGINT (CTRL-C) y SIGHUP (cierre de la terminal) usando la llamada al sistema sigaction().
  2. El manejador de señales debe:
    1. Mostrar un mensaje por la salida estándar cuando sea llamado por una señal que llegue al proceso. Esto ayudará a saber que funciona correctamente.
    2. Envíar una señal SIGTERM al proceso hijo creado con el fork().
Si lo hacemos correctamente, el proceso padre esperará a que el hijo termine en el wait(). Si el hijo termina por si solo, el proceso padre despertará del wait() y terminará. Si el proceso padre recibe una señal, a su vez pedirá al hijo que termine enviándole SIGTERM desde el manejador de señal. El manejador de señal en el padre se llamará, aunque el proceso esté esperando en wait(). Cuando el hijo termine, el proceso padre despertará del wait() y terminará.

Recursos

Ejemplos

El programa signals.c del repositorio de ejemplos muestra parte de la solución. Ese programa demuestra como usar sigaction() para instalar dos manejadores de señales: uno para SIGTERM, SIGINT y SIGHUP y otro para SIGSEV. También muestra cómo este puede mostrar mensajes en la salida estándar usando la llamada al sistema write().

Para resolver el ejercicio tenemos que coger el programa de la semana 4 y hacerle la siguientes modificaciones:

  1. Hacer todos los pasos requeridos para configurar la estructura sigaction y llamar a sigaction() antes del fork(). Con eso instalamos una función nuestra como manejador de señal.
  2. Asegurarnos que la variable con el PID del proceso es una variable global, para el que manejador de señal pueda tener acceso. Si es una variable local de main(), la función manejador de señal no tendrá acceso a dicha variable.
  3. El manejador de señal —que en signals.c se llama term_signal_handler()— debe mostrar el mensaje con write() y usar la llamada al sistema kill() para enviarle al proceso hilo la señal SIGTERM.

Última modificación: domingo, 21 de agosto de 2022, 19:09