-1

I have a Python-script which is started at bootup. In this I am trying to detect when the Raspberry is shutting down and at that time write some data to a file. However, the SIGTERM-handler is not getting activated.

What I have is this

import signal
import time

stopped = False

out = open('log.txt', 'w')

def stop(sig, frame):
    global stopped
    stopped = True
    out.write('caught SIGTERM\n')
    out.flush()

signal.signal(signal.SIGTERM, stop)

while not stopped:

    out.write('running\n')
    out.flush()
    print(str(time.time())+ ","  + str(stopped))

    time.sleep(1)

print("Caught Shutdown")

I am testing this using two Putty-terminals. In my first terminal I have the script executed, in the other one I am putting in

sudo shutdown -r

What I get in the first window with the Python-output is this:

1645909452.4044187,False
1645909453.4057834,False

Broadcast message from root@mypi on pts/1 (Sat 2022-02-26 22:04:14 CET):

The system is going down for reboot at Sat 2022-02-26 22:05:14 CET!

1645909454.4071815,False
1645909455.4085443,False

Any idea why the SIGTERM is not "accepted"? Thanks a lot already for ideas or pointers

ye_ol_man
  • 37
  • 6
  • 2
    The script handles sigterm correctly when `kill -TERM ` is used. Are you sure that your implementation of `shutdown` sends SIGTERM to all processes? – Arkadiusz Drabczyk Feb 26 '22 at 21:26
  • Hmm, systemd should send SIGTERM to all process if I'm reading systemd/src/shutdown/shutdown.c correctly. Can you look for `Sending SIGTERM to remaining processes` logs? – Arkadiusz Drabczyk Feb 26 '22 at 21:42
  • With the ``` kill -TERM ```` I get the handler executed, however with a "sudo reboot" or "sudo shutdown -r" I don't get any activity. The only thing i see on the shutdown is the broadcast. Where would i have the log? – ye_ol_man Feb 26 '22 at 21:54
  • But wait, when you run `shutdown -r` system will reboot in one minute, not now. You have to use `now` option to make it reboot now and that will also kill your SSH session, you should connect with serial wire to see the message printed by your script. Also when `time.sleep()` is running signal handlers will not be executed. – Arkadiusz Drabczyk Feb 26 '22 at 22:00

1 Answers1

-1

There are 2 issues here.

First, sudo shutdown -r does not shutdown system immediately but schedules shutdown in one minute from now as explained in SHUTDOWN(8):

SYNOPSIS
       shutdown [OPTIONS...] [TIME] [WALL...]
(...)

The time string may either be in the format "hh:mm" for hour/minutes
specifying the time to execute the shutdown at, specified in 24h clock
format. Alternatively it may be in the syntax "+m" referring to the
specified number of minutes m from now.  "now" is an alias for "+0",
i.e.  for triggering an immediate shutdown. If no time argument is
specified, "+1" is implied.

You have to run shutdown -h now to shutdown the system now.

The second issue is that you most likely use you RPi over ssh and even though systemd sends SIGTERM to all processes on reboot ssh can be killed by systemd first what will cause your shell and subsequently your python script to get SIGHUP signal and die before it receives SIGTERM signal. Run your script with nohup like that to make it ignore SIGHUP:

pi@raspberrypi:~ $ nohup  ./s.py
nohup: ignoring input and appending output to 'nohup.out'

Now reboot system and make sure that it received SIGTERM when it's back up:

pi@raspberrypi:~ $ tail  log.txt
running
running
running
running
caught SIGTERM

Alternatively, install a separate SIGHUP handler.

Arkadiusz Drabczyk
  • 11,227
  • 2
  • 25
  • 38
  • Hey Arkadiusz, thanks for that pointer with the nohup, this brings the script into the handler. Thanks a lot! – ye_ol_man Feb 27 '22 at 13:37
  • Hello again Arkadiusz, from what I see there is different behaviour on how I start my script. When I go for `nohup python ./s.py` from the terminal then the handler works. When the script is started via crontab then I do not see any effect of the handler. This seems to be expected behaviour from what I have seen. Any idea how to circumvent that? The cronjob of the script is started at @reboot and the reboot happens daily at a given time. – ye_ol_man Feb 27 '22 at 15:07
  • I encourage you to familiarize yourself with crontab manual - `@reboot` actions are performed when crond starts, not when system is rebooted. – Arkadiusz Drabczyk Feb 27 '22 at 21:40
  • Hello Arkadiusz, sorry I was unprecise. The script would start up when crond starts up which is at boot-time. During normal operation of the RPi it will do its thing, collect data and log that. However I need to flush out some data when the RPi shuts down to not loose data. That's the reason why I need to detect the shut-down situation. So `@reboot` is the correct time for starting the script. 8o) – ye_ol_man Feb 28 '22 at 12:22