0

I use some Python bindings to a C++ based library which starts some processes.

I have the problem that while the execution is within that code-path it does not "feel" a SIGINT, but as soon that context is finished, the Python process the SIGINT and use my defined handler. What is the proper procedure to "broadcast" a signal to all running sub-processes?

1
  • Please show code or a system call trace, etc. Probably your C++ library is calling system, which ignores SIGINT — but we can only guess without a fuller problem description. Commented Mar 10 at 11:32

2 Answers 2

1

When using Python bindings to a C++ library that spawn processes, the SIGINT might not be received by all child processes. Instead, Python only processes SIGINT once execution returns to its scope.

To prevent this behavior, you may want to try process groups - setpgrp - set the process group ID.

For example:

  1. Group all spawned processes together

  2. Handle signals in Python

  3. Forward the signal captured to the entire process group

Code example:

import os
import signal
import sys
from types import FrameType
from typing import NoReturn

# Set the current process in its own process group
os.setpgrp()


def signal_handler(signalnum: int, _: FrameType) -> NoReturn:
    # Ignore the captured signal number while handling it to prevent maximum recursion depth
    signal.signal(signalnum=signalnum, handler=signal.SIG_IGN)

    print(f"Received signal {signalnum}")

    # Send signal to all processes in the group
    os.killpg(0, signalnum)
    # Exit the execution
    sys.exit(1)


# Configure the signals you want to capture
# Capture SIGINT (Ctrl+C) and call `signal_handler` custom function
signal.signal(signalnum=signal.SIGINT, handler=signal_handler)

# Your code
...

I hope this helps!

Sign up to request clarification or add additional context in comments.

2 Comments

As @markus-hirsimäki presented in their answer, you can try&catch the ProcessLookupError or PermissionError that could potentially raise the os.kill() function.
Thanks a lot! Unfortunately it does not work; what i can see is this: imgur.com/hC69OXA what i try to stop is that thread that does the transfer. From the looks of it, it seems that python lose control when that thread is started and regain control when that process is finished. From another terminal i can send TERM/KILL to the exact PID of that thread and the whole process is terminated/kill but if i send SIGINT to that specific pid nothing happens
0

You can use this style to send a sigint to a given PID. You should capture or search for the PID when creating the subprocess.

import os
import signal

def send_sigint(pid):
    try:
        os.kill(pid, signal.SIGINT)
        print(f"SIGINT signal sent to process {pid}")
    except ProcessLookupError:
        print(f"No process found with PID {pid}")
    except PermissionError:
        print(f"Permission denied to send SIGINT to process {pid}")

pid = 12345  # Replace with the actual PID
send_sigint(pid)

Or alternatively using subprocess

import subprocess
import signal

process = subprocess.Popen(..)
process.send_signal(signal.SIGINT)

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.