Skip to content

Negative run-time reported by subprocess.run's TimeoutExpired exception when setting timeout=0 #133089

Closed

Description

@vadimkantorov

Bug report

Bug description:

import subprocess
subprocess.run(['echo', 'hi'], timeout = 0)

# subprocess.TimeoutExpired: Command '['echo', 'hi']' timed out after -0.00010189996100962162 seconds
# subprocess.TimeoutExpired: Command '['echo', 'hi']' timed out after -4.819990135729313e-05 seconds

This is quite unexpected that the measured run-time can be negative

In general, it's unclear in the docs what behavior should have timeout=0. I would propose that it should disable timeout control, and should be equivalent to timeout=None.

But in any case, negative run-times are quite strange :)

CPython versions tested on:

3.12

Operating systems tested on:

WSLv1+Ubuntu24.04

Linked PRs

Activity

  1. added
    stdlibStandard Library Python modules in the Lib/ directory
    on Apr 28, 2025
  2. added a commit that references this issue on Apr 28, 2025
  3. vadimkantorov commented on Apr 30, 2025

    @vadimkantorov
    Author

    Btw, even outside of unspecified behavior for timeout=0, setting timeout to a very small value also prints negative time measurement:

    import subprocess
    subprocess.run(['echo', 'hi'], timeout = 1e-9)
    
    # subprocess.TimeoutExpired: Command '['echo', 'hi']' timed out after -2.162200007660431e-05 seconds

    How can time measurement be negative? Is it indicative of some other bug related to execution time measurement?

  4. gpshead commented on May 3, 2025

    @gpshead
    Member

    if someone specifies an unrealistically small timeout such as 0 or 0.00001 they should expect to get a TimeoutError. timeout=0 should not disable the timeout. Requiring None for that is not a bug.

    It'd be reasonable to raise ValueError if the timeout supplied were < 0 but I would not consider that a bugfix.

    The tiny negative number in the error message in this case is due to timeout math being floating point, inexact, and fuzzy on posix it is calculated as an time delta of remaining time between steps and thus floating point precision can yield an odd looking result. the value in the error message is not the original timeout passed into the API call as that is not preserved and passed through into the self.wait(timeout=self._remaining_time(endtime)) call within Popen._communicate that raises in this specific case.

  5. vadimkantorov commented on May 3, 2025

    @vadimkantorov
    Author

    timeout=0 should not disable the timeout. Requiring None for that is not a bug.

    I propose that semantics of this edge case is explained clearly in the docs. Because in different systems the semantics of timeout=0 is different, e.g. in bash export TMOUT=0 diables the auto-logout timeout

    For the negative number, of course I realize that it's most likely an artifact of some calculation, but it is again very surprising to see it as end user and there might be a suspicion of some bug somewhere. I propose that it's mentioned in the docs somewhere - or clipped up to zero to fix up the semantics


    (Allowing timeout=0 to have disabling semantics can simplify types to just being "float" instead of "float | None" in client user code, where the timeout value gets passed around many layers of indirection (including e.g. configs)

  6. gpshead commented on May 4, 2025

    @gpshead
    Member

    I think the awkward error message is fixable, i left a note on the PR to see if they want to try doing that.

  7. added a commit that references this issue on May 5, 2025
  8. added a commit that references this issue on May 5, 2025
  9. gpshead commented on May 5, 2025

    @gpshead
    Member

    thanks for the report and contributions!

  10. added a commit that references this issue on May 5, 2025
  11. picnixz commented on May 5, 2025

    @picnixz
    Member

    I also thought about the floating-point computation being flaky but AFAIR, the timeout is computed using a monotonic clock so that's surprising. Or maybe the monotonic clock was not used in this specific case?

  12. added a commit that references this issue on Jul 12, 2025
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

    3.13only security fixes3.14bugs and security fixesstdlibStandard Library Python modules in the Lib/ directorytopic-subprocessSubprocess issues.type-bugAn unexpected behavior, bug, or error

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions