GV

GeezerVison

The World Wide Web, restored to 800 pixels of glory.

Home|About|Gaming cabinet|Archives|How it works|Starter sites

On this site

  • Sign in
  • ActionsCI/CD and automation
  • CodespacesCloud development environments
  • All Features
  • Documentation
  • Training
  • Certifications
  • Build with Copilot
  • Customize Copilot
  • Integrations
  • Trending repos
  • GitHub Sponsors
  • Developer articles
  • Enterprises

This view

  • Original page
  • New address

GeezerVison is showing github.com — Add `multiprocessing.Process.interrupt` · Issue #131913 · python/cpython

Add multiprocessing.Process.interrupt #131913

New issue
Copy link
New issue
Copy link
Closed
Closed
Add multiprocessing.Process.interrupt#131913
Copy link
Assignees
pulkin
Labels
stdlibStandard Library Python modules in the Lib/ directoryStandard Library Python modules in the Lib/ directorytopic-multiprocessingtype-featureA feature request or enhancementA feature request or enhancement

Description

@pulkin
pulkin
opened on Mar 30, 2025
Issue body actions

Feature or enhancement

Proposal:

We have .terminate() and .kill() but not .interrupt() for terminating multiprocessing.Process. I believe the latter could be a useful addition when we have a python subprocess that we want to terminate in a "normal" way: i.e. triggering finalizers, etc.

This roughly demonstrates the difference when using one or the other (linux):

from signal import SIGINT
from multiprocessing import Process
from time import sleep

def payload():
    try:
        print("working")
        sleep(10)
    finally:
        print("a very important teardown")

print("> kill or terminate")
p = Process(target=payload)
p.start()
sleep(1)
p.kill()  # or terminate

output

> kill or terminate
working
class MyProcess(Process):
    def interrupt(self):
        return self._popen._send_signal(SIGINT)

print("> interrupt")
p = MyProcess(target=payload)
p.start()
sleep(1)
p.interrupt()

output

> interrupt
working
a very important teardown
Process MyProcess-2:
Traceback (most recent call last):
  File "/usr/lib64/python3.13/multiprocessing/process.py", line 313, in _bootstrap
    self.run()
    ~~~~~~~~^^
  File "/usr/lib64/python3.13/multiprocessing/process.py", line 108, in run
    self._target(*self._args, **self._kwargs)
    ~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "test.py", line 9, in payload
    sleep(10)
    ~~~~~^^^^
KeyboardInterrupt

Motivation for sending SIGINT to subprocesses in general:

  • it allows usual python patterns in the payload: we can now define finally, with, etc. and expect them to trigger normally
  • SIGINT is a very lean way to cancel heavy payloads. It is widely supported such that if you have non-pure-python stack you still have higher chances to exit gracefully
  • I also think it enables a better interaction with nested subprocesses: if a subprocess S manages some Pool or concurrent object, sending SIGINT to S will let nested subprocesses to exit gracefully as opposed to, for example, leaving orphans on linux. A pure nested Process will still leave orphans but you can write some code in the payload to work with this:
def payload():
    try:
        p = MyProcess(target=inner)
        p.start()
        p.join()
    finally:
        p.interrupt()

Motivation for having Process.interrupt() in the standard library:

  • it is very easy to misuse terminate or kill without understanding the consequences or particularities of the two. .interrupt could become the default or recommended way to interrupt long-running tasks. Even without any payload-specific code, it prints error and python stack trace on termination which is a good starting point to write and debug multiprocessing code, thus, making it a friendlier environment
  • I feel like an average developer knows more about the difference between .interrupt and .kill than between .terminate and .kill. This is subjective, of course, but, discarding internal reasons to have both .terminate and .kill, I do not understand how .interrupt is not in this list.

Has this already been discussed elsewhere?

This is a minor feature, which does not need previous discussion elsewhere

Links to previous discussion of this feature:

No response

Linked PRs

  • gh-131913: multiprocessing: add interrupt for POSIX #132453

Activity

  1. pulkin
    added
    type-featureA feature request or enhancementA feature request or enhancement
    on Mar 30, 2025
  2. picnixz commented on Mar 30, 2025

    @picnixz
    picnixz
    on Mar 30, 2025
    Member
    More actions

    This is a minor feature, which does not need previous discussion elsewhere

    Force shutdown via kill() and terminate() on ProcessPoolExecutor (not multiprocessing.Process) required a discussion so I think this one also needs a discussion (see discuss.python.org/t/cancel-running-work-in-processpoolexecutor/58605/1 and #128041).

    I don't have time to expand here so I'll leave it to @gpshead (or I'll do it later)

  3. picnixz
    added
    stdlibStandard Library Python modules in the Lib/ directoryStandard Library Python modules in the Lib/ directory
    topic-multiprocessing
    on Mar 30, 2025
  4. picnixz
    added this to Multiprocessing issueson Mar 30, 2025
  5. gpshead commented on Mar 30, 2025

    @gpshead
    gpshead
    on Mar 30, 2025
    Member
    More actions

    I don't mind the idea if a .interrupt method that plumbs through sending a SIGINT on POSIX similar to how terminate works with SIGTERM.

    Note that on Windows this concept does not really appear to exist. CTRL_C_EVENT or CTRL_BREAK_EVENT goes to an entire process group.

    So decide up front what the Windows behavior should be. Would the .interrupt API not exist there? Would it raise there? Is it another terminate equivalent there (which feels undesirable)?

    On POSIX people can already setup SIGTERM handlers; but doing so in the context of a multiprocessing child process is awkward, so it is understandable to want an easier way to use SIGINT.

    They could also already send a SIGINT with something similar to:

    if process.is_alive() and process.pid is not None:
        signal.kill(process.pid, signal.SIGINT)  # race condition with the above checks?

    so this is more of a convenience wrapper around that. literally just this in multiprocessing/popen_fork.py

        def interrupt(self):
            self._send_signal(signal.SIGINT)

    with the question being what to put in multiprocessing/popen_spawn_win32.py.

  6. pulkin commented on Mar 30, 2025

    @pulkin
    pulkin
    on Mar 30, 2025
    ContributorAuthor
    More actions

    If it can be worked out for individual processes ATM with GenerateConsoleCtrlEvent (assuming python binds SIGINT handlers to SetConsoleCtrlHandler) I would go for it. As far as I read your and Claude's comment, we will need to also change how the process is created. I'd love to test the latter but I am not a win user.

  7. gpshead commented on Mar 31, 2025

    @gpshead
    gpshead
    on Mar 31, 2025
    Member
    More actions

    I would not change how we create windows processes, that'd mess with expectations. if interrupt winds up only being reliably meaningful on POSIX, we just document it as such.

  8. pulkin commented on Mar 31, 2025

    @pulkin
    pulkin
    on Mar 31, 2025
    ContributorAuthor
    More actions

    Worth mentioning that signal(signal.SIGTERM, signal.default_int_handler) and using .terminate is as good for the purposes described in OP. Presumably, this recipe does not have the aforementioned issues on win.

  9. pulkin commented on Apr 11, 2025

    @pulkin
    pulkin
    on Apr 11, 2025
    ContributorAuthor
    More actions

    Can I assign to myself and raise a MR?

  10. gpshead
    assigned
    pulkin
    on Apr 12, 2025
  11. gpshead commented on Apr 12, 2025

    @gpshead
    gpshead
    on Apr 12, 2025
    Member
    More actions

    yep, go ahead!

  12. pulkin commented on Apr 22, 2025

    @pulkin
    pulkin
    on Apr 22, 2025
    ContributorAuthor
    More actions

    Can you please check the MR?

  13. gpshead
    added a commit that references this issue on Apr 23, 2025

    gh-131913: multiprocessing: add interrupt for POSIX (GH-132453)

    77605fa
  14. gpshead commented on Apr 23, 2025

    @gpshead
    gpshead
    on Apr 23, 2025
    Member
    More actions

    merged, thanks!

  15. gpshead
    closed this as completedon Apr 23, 2025
  16. github-project-automation
    moved this to Done in Multiprocessing issueson Apr 23, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

  • @pulkin
    pulkin

Labels

stdlibStandard Library Python modules in the Lib/ directoryStandard Library Python modules in the Lib/ directorytopic-multiprocessingtype-featureA feature request or enhancementA feature request or enhancement

Projects

  • Multiprocessing issues
    Status
    Done
    Show more project fields

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions

You are visitor 01402503 — GeezerVison does not store the pages you look up.
Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required.