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 — `asyncio.create_subprocess_shell` does not consistently result in negative `returncode` on signal termination · Issue #138234 · python/cpython

asyncio.create_subprocess_shell does not consistently result in negative returncode on signal termination #138234

New issue
Copy link
New issue
Copy link
Closed
Closed
asyncio.create_subprocess_shell does not consistently result in negative returncode on signal termination#138234
Copy link
Labels
stdlibStandard Library Python modules in the Lib/ directoryStandard Library Python modules in the Lib/ directorytopic-asynciotype-bugAn unexpected behavior, bug, or errorAn unexpected behavior, bug, or error

Description

@danielrainer
danielrainer
opened on Aug 29, 2025
Issue body actions

Bug report

Bug description:

The docs for returncode state the following:

A negative value -N indicates that the child was terminated by signal N (POSIX only).

which does not technically require, but strongly suggest that processes terminated by signals will have a negative returncode corresponding to the signal. On some platforms (observed on Arch Linux and macOS, both using Python 3.13.7), this does indeed seem to be the case. On others it is not. The observed counterexample is Ubuntu using Python 3.12.3. There, returncode seems to be set to 128 + signal value. Technically, this does not violate the documented behavior, but it is very surprising. If that is intended behavior, the docs deserve a clear warning. My preference would be to mandate negative returncodes upon termination by signal in the docs and to adapt the code on non-conformant platforms accordingly.

Interestingly, asyncio.create_subprocess_exec has the expected behavior of consistently negative returncodes on the tested platforms, which increases my suspicion that there is indeed undesired behavior involved.

import asyncio


async def repro():
    proc = await asyncio.create_subprocess_shell("./sigint.sh")
    await proc.communicate()
    print(proc.returncode)
    assert proc.returncode == -2


asyncio.run(repro())

sigint.sh:

#!/bin/sh
kill -2 $$

I created a repo to show the differences in GitHub's CI: https://github.com/danielrainer/python_signal_returncode_repro/actions/runs/17310888203

CPython versions tested on:

3.13, 3.12

Operating systems tested on:

Linux, macOS

Linked PRs

  • gh-138234: clarify returncode behavior for subprocess_exec vs subprocess_shell #138536
  • [3.14] gh-138234: clarify returncode behavior for subprocesses created with shell=True (GH-138536) #146254
  • [3.13] gh-138234: clarify returncode behavior for subprocesses created with shell=True (GH-138536) #146255

Activity

  1. danielrainer
    added
    type-bugAn unexpected behavior, bug, or errorAn unexpected behavior, bug, or error
    on Aug 29, 2025
  2. StanFromIreland
    added
    topic-asyncio
    stdlibStandard Library Python modules in the Lib/ directoryStandard Library Python modules in the Lib/ directory
    on Aug 29, 2025
  3. github-project-automation
    added this to asyncioon Aug 29, 2025
  4. github-project-automation
    moved this to Todo in asyncioon Aug 29, 2025
  5. andreuu-tsai commented on Sep 5, 2025

    @andreuu-tsai
    andreuu-tsai
    on Sep 5, 2025
    Contributor
    More actions

    When using create_subprocess_shell, proc.returncode is 130 after sending SIGINT.
    When using create_subprocess_exec, the return code is -2 as expected (terminated by SIGINT).

    The current documentation says:

    A negative value -N indicates that the child was terminated by signal N (POSIX only).

    This is accurate for create_subprocess_exec, where the child process is executed directly.
    But for create_subprocess_shell, the child is wrapped by /bin/sh, and the observed return code comes from the shell’s exit status rules (e.g. 128+N for termination by signal N).
    So in this case, the return code follows Bash Exit Status
    (or the corresponding shell), not the -N convention.

    Should the documentation clarify this difference between create_subprocess_exec (direct POSIX behavior) and create_subprocess_shell (shell exit status)?

  6. danielrainer commented on Sep 9, 2025

    @danielrainer
    danielrainer
    on Sep 9, 2025
    Author
    More actions

    Should the documentation clarify this difference between create_subprocess_exec (direct POSIX behavior) and create_subprocess_shell (shell exit status)?

    I think the documentation should accurately describe the behavior of the functions, that's the point of having documentation.

    Regarding the behavior of create_subprocess_shell, I get that forwarding the exit status of the shell is the simplest way of implementing returncode. Unfortunately, that makes it inconvenient for users of the interface to do anything useful with the returncode, since they would have to know about all possible shells which might be used and their respective conventions. It might not be realistic, or even desirable, to change the implementation to have consistent behavior on all (POSIX) platforms. If the current behavior is kept, there should be a clear indication that the shell's exit code is used, and that this code depends on which shell is used.

    Regardless of what is done wrt create_subprocess_shell, the documentation create_subprocess_exec should be clarified to state whether signal termination always results in a negative returncode indicating which signal caused termination. At the moment, an implementation which sometimes returns negative values as described when a signal terminates the process, but other times returns non-negative values for signal termination is allowed by the docs. I don't think this should ever happen, but from reading the docs I don't know if it could. If it actually can happen, it certainly should to be noted in the documentation.

  7. kumaraditya303
    added a commit that references this issue on Mar 21, 2026

    gh-138234: clarify returncode behavior for subprocesses created with …

    8a531f8
  8. miss-islington
    added 2 commits that reference this issue on Mar 21, 2026

    pythongh-138234: clarify returncode behavior for subprocesses created…

    f31b87a

    pythongh-138234: clarify returncode behavior for subprocesses created…

    bbaac99
  9. kumaraditya303
    closed this as completedon Mar 21, 2026
  10. github-project-automation
    moved this from Todo to Done in asyncioon Mar 21, 2026
  11. kumaraditya303
    added 2 commits that reference this issue on Mar 21, 2026

    [3.14] gh-138234: clarify returncode behavior for subprocesses create…

    f2c7024

    [3.13] gh-138234: clarify returncode behavior for subprocesses create…

    29303db
  12. CuriousLearner
    added a commit that references this issue on Mar 22, 2026

    Merge remote-tracking branch 'upstream/main' into fix-pythongh-138577

    2691ad9
  13. ljfp
    added a commit that references this issue on Apr 25, 2026

    pythongh-138234: clarify returncode behavior for subprocesses created…

    f797cd5
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    stdlibStandard Library Python modules in the Lib/ directoryStandard Library Python modules in the Lib/ directorytopic-asynciotype-bugAn unexpected behavior, bug, or errorAn unexpected behavior, bug, or error

    Projects

    • asyncio
      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.