New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WindowsError [Error 5] Access Denied when trying to terminate a process #1023

Closed
jackdbd opened this Issue Sep 25, 2017 · 1 comment

Comments

Projects
None yet
2 participants
@jackdbd

jackdbd commented Sep 25, 2017

  • gevent version: 1.2.2
  • Python version: Python 2.7.12 |Anaconda 2.5.0 (32-bit)
  • Operating System: Windows 10 64 bit

Description:

I'm using moviepy to read a video file. When creating a reader object moviepy calls FFmpeg in a process, gets some info about the video and then terminates the process.

I'm getting a WindowsError [Error 5] Access Denied when moviepy terminates the process with proc.terminate(). It seems an issue similar to this one.

Minimum example follows.

What I've run:

# Access denied when trying to call terminate
import gevent.monkey
gevent.monkey.patch_subprocess()
import subprocess as sp
proc = sp.Popen('dir', shell=True, stdout=sp.PIPE, stderr=sp.PIPE)
proc.terminate()

Here is the error I'm getting:

Traceback (most recent call last):
  File "C:\Anaconda2\lib\site-packages\IPython\core\interactiveshell.py", line 3066, in run_code
    exec(code_obj, self.user_global_ns, self.user_ns)
  File "<ipython-input-7-596c33b797ea>", line 1, in <module>
    proc.terminate()
  File "C:\Anaconda2\lib\site-packages\gevent\subprocess.py", line 982, in terminate
    TerminateProcess(self._handle, 1)
WindowsError: [Error 5] Zugriff verweigert (access denied)

This error does not occurr without applying the patch.

# no errors without monkey patching
import subprocess as sp
proc = sp.Popen('dir', shell=True, stdout=sp.PIPE, stderr=sp.PIPE)
proc.terminate()

I noticed that gevent/subprocess.py does not include the try/except block that is included in the subprocess.py module of the standard library.

# gevent/subprocess.py Popen.terminate
def terminate(self):
    """Terminates the process
    """
    TerminateProcess(self._handle, 1)
# subprocess.py Popen.terminate
def terminate(self):
    """Terminates the process
    """
    try:
        _subprocess.TerminateProcess(self._handle, 1)
    except OSError as e:
        # ERROR_ACCESS_DENIED (winerror 5) is received when the
        # process already died.
        if e.winerror != 5:
            raise
        rc = _subprocess.GetExitCodeProcess(self._handle)
        if rc == _subprocess.STILL_ACTIVE:
            raise
        self.returncode = rc
@jamadden

This comment has been minimized.

Member

jamadden commented Sep 25, 2017

Thank you for your report and analysis!

It looks like the stdlib code you reference was added in Python 3.1 and then backported to Python 2.7.4+ (the gevent subprocess module predates that). It added a suite of tests, but gevent doesn't run them (and it's not obvious to me why it doesn't, despite the comment that I wrote two years ago---it may have to do with the call to communicate).

On POSIX, at least, we know preemptively when the process is dead and don't bother trying to signal it, but we don't have child watchers on windows that would always tell us that. We could add a similar check there, but it would be an optimization: we'd still need the try/except logic.

jamadden added a commit that referenced this issue Sep 27, 2017

More safely terminate process on Windows.
Fixes #1023

Also re-enable the POSIX version of those tests. They should (and do)
pass.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment