---
og:title: Slurm signals
---

# ⏲️ Slurm signals


Una situación común es que un job se quede sin tiempo y SLURM lo cancele abruptamente,
sin oportunidad de guardar el estado o escribir algun mensaje.

Para evitar este corte repentino, SLURM permite configurar el envío automático de señales
a los procesos antes de que se cumpla el tiempo límite.
Esta funcionalidad se puede aprovechar para implementar un graceful shutdown:
una finalización controlada del trabajo que permita, por ejemplo,
guardar el progreso, generar un checkpoint, copiar archivos del `scratch` al `home`, etc.

A continuación un ejemplo de juguete para ser adaptado.

## Programa de ejemplo

Primero necesitamos un programa que haga cómputo.
Para simplificar el ejemplo, vamos a usar el siguiente script
que _simula_ hacer cálculos por 200 segundos.

```{code-block} bash
:linenos:
:caption: work.sh
#!/bin/bash

function sig_handler() {
         echo "$(date +"%H:%M:%S"): pid=$$: Executable interrupted, task=$SLURM_PROCID"
         exit 2
}

trap 'sig_handler' SIGTERM

echo $(date +"%H:%M:%S"): pid=$$: BEGIN form $(hostname)
sleep 200 &
wait
echo $(date +"%H:%M:%S"): pid=$$: END form $(hostname)
```

> La función `sig_handler` simplemente imprime un log si el proceso es cancelado.

##  Script de submit

El script va a llamar a nuestro programa,
cuando éste termine, llama a la función `save_results` que simula guardar el resultado.

* `SBATCH --time`: 10 minutos de límite, y el signal se lanza a los pocos segundos (a los 5 segundos, pero en la práctica no es exacto)
* `SBATCH --signal`: Configura la señal que enviará SLURM:
    - `SIGTERM`: _Signal Terminate_, solicita amablemente al proceso que termine.
    - `@595`: Cuantos segundos antes del límite se tiene que enviar la señal (9m55s).
    - `B:`: Si agregamos esto, la señal va al script. Sin esto, la señal va directamente al programa (ejecutado con srun).
* `srun` es bloqueante, por lo que cuando todas las tasks terminen o se cancelen, se va a llamar a `save_results`.

```{code-block} slurm
:linenos:
:caption: job.sh
#!/bin/bash
#SBATCH --partition=short
#SBATCH --nodes=2
#SBATCH --ntasks-per-node=1
## Format: days-hours:minutes
#SBATCH --time=0-0:10
## Format: sig_num@time-in-seconds
#SBATCH --signal=SIGTERM@595

. /etc/profile

function save_results {
	echo $(date +"%H:%M:%S"): Saving results

    for i in {0..100..10}
    do
        echo $(date +"%H:%M:%S"): Saving progress $i%...;
        sleep 10;
    done

    echo $(date +"%H:%M:%S"): Results saved
}

echo $(date +"%H:%M:%S"): Calling srun from $(hostname)

srun work.sh
save_results

echo $(date +"%H:%M:%S"): End of script
```

## Ejemplo de salida

* Podemos ver que el srun se ejecuta en el primer nodo.
* work.sh atrapa la señal e imprime su log.
* El exit code 2 confirma que el job terminó por la signal.
* El "proceso de guardado" corre por 100 segundos.

```{code-block}
:caption: slurm.out
12:37:02: Calling srun from ivb14.ivb.ccad.unc.edu.ar
12:37:02: pid=713874: BEGIN form ivb14.ivb.ccad.unc.edu.ar
12:37:02: pid=351777: BEGIN form ivb15.ivb.ccad.unc.edu.ar
slurmstepd: error: *** STEP 1052540.0 ON ivb14 CANCELLED AT 2024-06-04T12:37:04 ***
12:37:04: pid=713874: Executable interrupted, task=0
12:37:04: pid=351777: Executable interrupted, task=1
srun: error: ivb14: task 0: Exited with exit code 2
srun: error: ivb15: task 1: Exited with exit code 2
12:37:05: Saving results
12:37:05: Saving progress 0%...
12:37:15: Saving progress 10%...
12:37:25: Saving progress 20%...
12:37:35: Saving progress 30%...
12:37:45: Saving progress 40%...
12:37:55: Saving progress 50%...
12:38:05: Saving progress 60%...
12:38:15: Saving progress 70%...
12:38:25: Saving progress 80%...
12:38:35: Saving progress 90%...
12:38:45: Saving progress 100%...
12:38:55: Results saved
12:38:55: End of script
```


Si el programa terminal antes, el output tiene la siguiente pinta:

```{code-block}
:caption: slurm.out
13:10:44: Calling srun from rome52.rome.ccad.unc.edu.ar
13:10:44: pid=1880296: BEGIN form rome52.rome.ccad.unc.edu.ar
13:10:45: pid=1880296: END
13:10:46: pid=1433777: BEGIN form rome53.rome.ccad.unc.edu.ar
13:10:47: pid=1433777: END
13:10:47: Saving results
13:10:47: Saving progress 0%...
13:10:57: Saving progress 10%...
13:11:07: Saving progress 20%...
13:11:17: Saving progress 30%...
13:11:27: Saving progress 40%...
13:11:37: Saving progress 50%...
13:11:47: Saving progress 60%...
13:11:57: Saving progress 70%...
13:12:07: Saving progress 80%...
13:12:17: Saving progress 90%...
13:12:27: Saving progress 100%...
13:12:37: Results saved
13:12:37: End of script
```
