Notifications
Clear all

[Solved] Catch shutdown command in Python script

6 Posts
2 Users
1 Likes
111 Views
(@maximilian-sittinger)
Posts: 3
Active Member Customer
Topic starter
 

Hi,

 

I'm using the Witty Pi 4 L3V7 together with a Raspberry Pi Zero 2 WH.

I installed an external button that is connected to the SWITCH and GND Pins. Everything works as expected, I can turn the Raspberry Pi on and shut it down by pressing the button.

 

When pressing the button to shut down the Raspberry Pi, the

shutdown -h now

command is run.

 

For my use case, I want to do some clean up operations (e.g. writing information to log file) when the button is pressed while running a Python script.

I tried to implement this by handling the SIGTERM signal with:

signal.signal(signal.SIGTERM, sys.exit)

and then catching the SystemExit exception with:

except SystemExit:
    # Write info on external shutdown trigger (e.g. button) to log file
    logger.info("Script stopped by external trigger")

 

Unfortunately this does not work, the code in the except block is never executed.

 

I would appreciate any guidance on possible alternative approaches to achieve this result. Maybe I have to use the beforeShutdown.sh script in some way?

Thanks!

 
Posted : 12/04/2024 6:53 pm
(@admin)
Posts: 315
Member Admin
 

This scenario has been considered, and the solution is to call your cleanup script(s) in the beforeShutdown.sh file.

You will need to use absolute/complete path for each command in that file, otherwise it may not be found.

 
Posted : 13/04/2024 9:27 am
(@maximilian-sittinger)
Posts: 3
Active Member Customer
Topic starter
 

Thanks for the advice!

 

I have added the following commands to the beforeShutdown.sh file:

# Send SIGTERM signal to all running python3 processes
/usr/bin/killall -15 python3

# Wait for all python3 processes to exit
while /usr/bin/pgrep python3 >/dev/null; do
    /usr/bin/sleep 1
done

 

I am catching the SIGTERM signal in the Python scripts with the following code:

import signal

def signal_handler(sig, frame):
    """Handle a received signal by raising a SystemExit exception."""
    raise SystemExit

signal.signal(signal.SIGTERM, signal_handler)

try:
    ### main code ###

except SystemExit:
    logger.info("Script stopped by external trigger")

finally:
    ### cleanup operations ###

 

With this combination, everything works as expected: if the button (connected to the Witty Pi 4 L3V7) is pressed while the Raspberry Pi is still running, a SIGTERM signal is send to all running scripts, where it is caught to perform the cleanup operations. When these are finished, the normal shutdown procedure is continued.

 

There is only one problem: It seems like the timer for the power cut delay value starts immediately after pressing the button. E.g. if the power cut delay is set to 10 seconds and it takes ~8 seconds to finish the running scripts, the power is cut before doing the clean shutdown. The documentation for the power cut delay states that "Default value is 5.0 seconds, which means Witty Pi will fully cut the power after 5 seconds since Raspberry Pi has been shut down." However, it seems like this is only true in the case of a "internal" shutdown command? For my use case, there may be scripts running that take more than the maximum amount of 25 seconds for the power cut delay value to finish.

 

Could you give any details on this behaviour? Thanks!

 

 
Posted : 15/04/2024 7:56 pm
(@admin)
Posts: 315
Member Admin
 

@maximilian-sittinger The power cut delay was initially counted from the moment that TXD goes down, which means the Pi has been shutdown. However this behavior has been changed since firmware 0x03: the counter now starts counting when the button is clicked or GPIO-4 is pulled down. The purpose of this change is to make sure the power can be cut when the Pi crashs during the shutdown (TXD will never go down if Pi hangs during shutdown).

Usually 25 seconds should be considered long enough for doing some cleanup work. If it is not the case for you, you may consider modifying the firmware (the firmware is fully open-sourced), to allow even longer delay before power cut. However such kind of modification is out of our scope of technical support.

 

 

 
Posted : 16/04/2024 9:38 am
(@maximilian-sittinger)
Posts: 3
Active Member Customer
Topic starter
 

Okay, thanks for the important information!

Maybe update the documentation to make this behaviour clear, I think the power cut is an important feature that should be understood correctly to avoid potential problems (e.g. power cut too early).

 

Just to be sure: Would it be possible to add this as optional setting, that the user can decide between the pre-0x03 behaviour (power cut delay counted after shutdown) and the current behaviour (power cut delay counted after button press/GPIO-4 pulled down)?

 
Posted : 16/04/2024 10:45 am
(@admin)
Posts: 315
Member Admin
 

@maximilian-sittinger the document has been updated accordingly.

Witty Pi 4 uses ATtiny841 as MCU, which only has 8k programing space. The current firmware has almost used up all of the space, so adding complex logic would be very difficult.

 
Posted : 17/04/2024 8:39 am
maxsitt reacted
Join Waitlist We will inform you when the product arrives in stock. Please leave your valid email address below.