0

Background:

I have a C# program that I run under Mono on Linux (specifically Raspbian). I am working on a Python script that starts that program, monitors it, and gracefully kills it. I use subprocess.Popen to run the C# program under mono. When I run the Python normally, I am able to send a SIGINT to the process and I can see it receive it and clean itself up nicely before exiting.

Problem: I want to be able to run the script as a SystemD service, so I created a simple SystemD service file. Now, the C# no longer gracefully exits, instead terminating immediately almost like a SIGKILL was sent instead of a SIGINT.

Here is my current simple testing code for working through this problem:

import os
import signal
import time
import subprocess

call = ['mono', '/home/user/test.exe'] # (not the actual name of the program, changed for this post)

print('starting')
process = subprocess.Popen(call)

time.sleep(20)
print('sending term')
process.send_signal(signal.SIGINT)
print('term sent')

And here is my SystemD service file (changed my actual username to 'user'):

[Unit]
Description=Test
After=multi-user.target

[Service]
User=user
Group=user
WorkingDirectory=/home/user/testcode
Type=simple
ExecStart=/home/user/testcode/.venv/bin/python /home/user/testcode/test.py
StandardOutput=syslog
StandardError=syslog
SyslogIdentifier=testcode

[Install]
WantedBy=multi-user.target

I've tried watching HTOP to see if there is anything weird going on with what the PID and GID are of the Mono processes, but everything looks more or less the same between the direct launch and SystemD launched Python script.

Unfortunately the Mono program is a bit of a black box to me so I have minimal insight into what is going on in it. I do have access to the source code, but I have no experience with C# and wouldn't know where to start to look for clues. I am able to tell if it quits gracefully as it generates a log file that I can tail and prints out a couple lines when it is exiting properly. Those lines do not get printed when it is forcefully terminated.

What I've Tried I've mostly experimented with different methods of launching the program using Popen.

  • Using shell=Truecauses the C# program to not be stopped at all when launched normally, but when launched via SystemD, it exhibits the same non-graceful quit behavior as without shell=True.
  • I tried some suggestions from this thread, namely using preexec_fn=os.setsid and os.killpg(os.getpgid(pro.pid), signal.SIGTERM) from the first answer with and without shell=True with no luck. Both normal launch and SystemD launch exhibit non-graceful quits.
  • I added time.sleep(5) to the end of the script to give the C# time to exit before the script exits. No change. My thought was that SystemD sees the Python script exit, and cleans up all other processes it spawned before they have a chance to exit gracefully.
bhagen
  • 9
  • 3
  • You don't wait for the process to exit. Once your service exits, systemd cleans up after it and kills the processes started by the service. – Dan D. Feb 03 '20 at 05:21
  • I think I ruled this out by adding a 5 second sleep to the end of the script. The program usually takes less than a second to clean up and exit so that should have been plenty of time. Instead, I can see the program get killed in HTOP when the signal is sent, then the python exits 5 seconds later. – bhagen Feb 03 '20 at 20:00

0 Answers0