Skip to content

Popen.poll always returns None #46727

Closed
Closed

Description

@jjcogliati
BPO 2475
Nosy @terryjreedy
Files
  • unnamed
  • Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.

    Show more details

    GitHub fields:

    assignee = None
    closed_at = <Date 2010-06-19.03:21:17.666>
    created_at = <Date 2008-03-24.20:59:08.849>
    labels = ['type-bug']
    title = 'Popen.poll always returns None'
    updated_at = <Date 2010-08-06.19:52:01.011>
    user = 'https://bugs.python.org/jjcogliati'

    bugs.python.org fields:

    activity = <Date 2010-08-06.19:52:01.011>
    actor = 'dandrzejewski'
    assignee = 'none'
    closed = True
    closed_date = <Date 2010-06-19.03:21:17.666>
    closer = 'terry.reedy'
    components = []
    creation = <Date 2008-03-24.20:59:08.849>
    creator = 'jjcogliati'
    dependencies = []
    files = ['17719']
    hgrepos = []
    issue_num = 2475
    keywords = []
    message_count = 7.0
    messages = ['64439', '64901', '64911', '68228', '70347', '107967', '108160']
    nosy_count = 6.0
    nosy_names = ['terry.reedy', 'roudkerk', 'jjcogliati', 'lisanke', 'reiko', 'dandrzejewski']
    pr_nums = []
    priority = 'normal'
    resolution = 'out of date'
    stage = None
    status = 'closed'
    superseder = None
    type = 'behavior'
    url = 'https://bugs.python.org/issue2475'
    versions = ['Python 2.5']

    Activity

    1. jjcogliati commented on Mar 24, 2008

      jjcogliatimannequin
      MannequinAuthor

      I was trying to use subprocess to run multiple processes, and then wait
      until one was finished. I was using poll() to do this and created the
      following test case:
      #BEGIN
      import subprocess,os

      procs = [subprocess.Popen(["sleep",str(x)]) for x in range(1,11)]
      
      while len(procs) > 0:
          os.wait()
          print [(p.pid,p.poll()) for p in procs]
          procs = [p for p in procs if p.poll() == None]
      #END

      I would have expected that as this program was run, it would remove the
      processes that finished from the procs list, but instead, they stay in
      it and I got the following output:

      #Output
      [(7426, None), (7427, None), (7428, None), (7429, None), (7430, None),
      (7431, None), (7432, None), (7433, None), (7434, None), (7435, None)]
      #above line repeats 8 more times
      [(7426, None), (7427, None), (7428, None), (7429, None), (7430, None),
      (7431, None), (7432, None), (7433, None), (7434, None), (7435, None)]
      Traceback (most recent call last):
        File "./test_poll.py", line 9, in <module>
          os.wait()
      OSError: [Errno 10] No child processes
      #End output

      Basically, even for finished processes, poll returns None.

      Version of python used:
      Python 2.5.1 (r251:54863, Oct 30 2007, 13:45:26)
      [GCC 4.1.2 20070925 (Red Hat 4.1.2-33)] on linux2

      Relevant documentation in Library reference manual 17.1.2
      poll( ) ... Returns returncode attribute.
      ... A None value indicates that the process hasn't terminated yet.

    2. roudkerk commented on Apr 3, 2008

      roudkerkmannequin
      Mannequin

      The problem is that os.wait() does not play nicely with subprocess.py.
      Popen.poll() and Popen.wait() use os.waitpid(pid, ...) which will
      raise OSError if pid has already been reported by os.wait().
      Popen.poll() swallows OSError and by default returns None.

      You can (sort of) fix your program by using
      "p.popen(_deadstate='dead')" in place of "p.popen()". This will make
      poll() return 'dead' instead of None if OSError gets caught, but this
      is undocumented.

      Maybe a subprocess.wait() function could be added which would return a
      tuple

      (pid, exitcode, popen_object)
      

      where popen_object is None if the process is "foreign" (i.e. it was
      not created by the subprocess module).

      It would not be hard to implement this on unix if you don't care about
      thread safety. (On unix Popen.wait() is not thread-safe either, so
      maybe thread safety does not matter.)

      To implement something similar on windows you would probably need to
      use WaitForMultipleObjects() to check whether any process handles are
      signalled, but that would involve patching _subprocess.c or using
      ctypes or pywin32.

    3. jjcogliati commented on Apr 4, 2008

      jjcogliatimannequin
      MannequinAuthor

      Hm. Well, after filing the bug, I created a thread for each subprocess,
      and had that thread do an wait on the process, and that worked fine.
      So, I guess at minimum it sounds like the documentation for poll could
      be improved to mention that it will not catch the state if something
      else does. I think a better fix would be for poll to return some kind
      of UnknownError instead of None if the process was finished, but python
      did not catch it for some reason (like using os.wait() :)

    4. lisanke commented on Jun 15, 2008

      lisankemannequin
      Mannequin

      Isn't this a critical problem. The .poll() function serves as a means to
      check the status of the process started. When it continues to report
      'None' to a process which has already terminated, it creates a false
      positive of a hung process. Dealing with recovery from an actual hung
      process is difficult enough. Having to deal with a bad detection that
      the process ran to completion on top of this, makes the use of
      subprocess difficult.

      Maybe I'm miss applying the .poll() function. I'm trying to detect that
      a process has hung, prior to calling .stdout.readlines(). The
      readlines() will hang my python script if the process is hung. Is there
      another way I should be doing this?

      Thanks,

      Mike

    5. reiko commented on Jul 28, 2008

      reikomannequin
      Mannequin

      I have also run into this problem. If you only use p.poll() and never
      p.wait(), returncode will always remain None.

      roudkerk's workaround doesn't seem to work with the new Popen objects,
      at least in python 2.4. ("unexpected keyword argument '_deadstate'")
      Does anyone have a workaround for subprocess.Popen? Do I have to switch
      to the deprecated popen function(s)?

    6. terryjreedy commented on Jun 17, 2010

      @terryjreedy
      Member

      Should this be closed or is this still a problem in 2.7 (release candidate out now, final soon) or 3.1?

    7. lisanke commented on Jun 19, 2010

      lisankemannequin
      Mannequin

      Terry,

      I had long since coded around the problem. At this point, I no longer have
      the test environment to cause the intermittent conditions of the process
      hang. I could code something up, but; your question is the first response to
      this bug report since "reiko <[email protected]>" on 7/28/2008. I
      suggest it can be closed, and would be reopened when encountered again. I
      appears nobody is working in that area of code.

      On Wed, Jun 16, 2010 at 8:13 PM, Terry J. Reedy <[email protected]>wrote:

      Terry J. Reedy <[email protected]> added the comment:

      Should this be closed or is this still a problem in 2.7 (release candidate
      out now, final soon) or 3.1?

      ----------
      nosy: +tjreedy


      Python tracker <[email protected]>
      <http://bugs.python.org/issue2475\>


    8. transferred this issue fromon Apr 10, 2022
    9. norswap commented on Jan 12, 2024

      @norswap

      This issue is still alive and well for me.

      I'm running Python 3.10.13 on Apple Silicon Mac.

      I'm sending Popen.terminate() to a subprocess, and I want to ensure that it does terminate within a certain delay, otherwise I send it Popen.kill(). To check if the process is terminated, I use Popen.poll() — which always returns None, even when the process is not actually terminated (in some case, it doesn't even terminate later).

      A workaround that works: using Popen._internal_poll(_deadstate="dead") — as when the thread is dead it will return "dead" instead of None.

      A potential complication is that I'm running all of this from a signal handler or an atexit handler. I want to make sure that all sub-processes have exited when the main process exits.

      I tried using Popen.wait(0.001) right before the poll call, given the implications of some messages in this thread, however this caused the process to terminate right there and then without any diagnostic whatsoever as to what was happening.

      Can I suggest reopening this and actually fixing the behaviour of poll? Is seems fundamentally broken if it does not actually return the exit code of a completed subprocess.

    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

      type-bugAn unexpected behavior, bug, or error

      Projects

      No projects

        Milestone

        No milestone

        Relationships

        None yet

        Development

        No branches or pull requests

        Issue actions