Detect when a service is stopping

How can I detect inside my container that the container is stopping (killed)? I have a handler for ctrl-c, which works fine when I run it from ssh, but when it’s running as a service in Balena and the service is stopped (for example if I shut down the device, or if I just stop/restart the service), then my code doesn’t detect that it’s stopping, it’s just killed. It would be good to be able to know that it’s asked to be shut down so I can do some final cleanup.

Hi @HakanL !

balenaEngine (like Docker) will normally first send a SIGTERM to the container, wait for some time (10 seconds by default, IIRC), then send a SIGKILL. Ctrl+C, in the other hand, will send a SIGINT (i.e., a different signal).

So, to answer diretly to your question, essentially you need to handle the SIGTERM signal in your container.

I hope this helps! :slightly_smiling_face:

Thanks, that is very helpful. However, I have a catch for SIGTERM, but it’s not firing. I can verify it by sending kill -TERM to my pid, I log the signal and shut down. But when I click on Stop on the service in the dashboard then my app is just gone. This is what is logged (Set focus is a log line in my app before I click stop):

main  23:02:27.473 VRB [DMXCore.DMXCore100.Services.MenuFocusManager] Set focus to index 0
Killing service 'main sha256:98efdbfef2da1c6ffe971ac8172bdc2d4243a95f37402d140d96c217ea56d962'
Killed service 'main sha256:98efdbfef2da1c6ffe971ac8172bdc2d4243a95f37402d140d96c217ea56d962'
Service exited 'main sha256:98efdbfef2da1c6ffe971ac8172bdc2d4243a95f37402d140d96c217ea56d962'

For reference I’m using .NET (Core) 7, not sure if it’s related to this (.NET 5 apps can no longer intercept SIGINT signals (receive CancelKeyPress events) when running under Docker · Issue #51221 · dotnet/runtime · GitHub). However I have tested to capture all the different signals. One thing that I don’t know if it’s relevant is that I’m starting my .NET process from a script, so the start command in the Dockerfile is: CMD ["/usr/src/scripts/start.sh"], could that cause problems where the signals aren’t sent to the (sub)process?

Turns out it was a combination of .NET and how I launch it that caused my problem. I wasn’t using exec in my start script (see this: bash - How to catch SIGTERM properly in Docker? - Stack Overflow), and after that I was able to catch the event in System.Runtime.Loader.AssemblyLoadContext.Default.Unloading.
If I used STOPSIGNAL SIGINT in my Dockerfile then my Console.CancelKeyPress event was fired instead.

1 Like