Skip to content
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

[Windows]Evenlet patched Subprocess.run/Popen blocked when Popen.communicate is used #799

Open
6769 opened this issue Jun 1, 2023 · 0 comments

Comments

@6769
Copy link

6769 commented Jun 1, 2023

version

Python==3.10.11, 3.8.10
eventlet==0.33.3
greenlet==2.0.2
dnspython==2.3.0

Tested on (Windows 10 LTSC)

problem

on Linux, the code followed could run and finished normally.

But on Windows, the patched subprocess.Popen function will block thread when trying to send some bytes to process object,
and it will be ok if stdin input was not used or just delete the eventlet.monkey_patch().

import unittest, os, shlex, subprocess
import eventlet;eventlet.monkey_patch()
iswin = os.sep != '/'


class EventletTestCase(unittest.TestCase):
    def test_communicate(self):
        cmd = 'cmd' if iswin else 'sh'
        p: subprocess.Popen = subprocess.Popen(shlex.split(cmd), stdin=subprocess.PIPE, stdout=subprocess.PIPE,
                                               stderr=subprocess.PIPE)
        r = p.communicate(b'uname -a', timeout=1)  # ============blocked============
        print(r)
        p.terminate()

    def test_direct_call(self):
        cmd = 'cmd /c dir' if iswin else 'sh -c ls'
        r = subprocess.run(shlex.split(cmd))
        print(r)


if __name__ == '__main__':
    unittest.main()

save the unittest code to file named as test_1.py and run it with python test_1.py -v,
will get blocked command output like these on windows:

python .\test_1.py -v
test_communicate (__main__.EventletTestCase) ... 

manually kill the blocked cmd.exe, it goes like:

======================================================================
ERROR: test_communicate (__main__.EventletTestCase)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "C:\Library\eventlet1\test_1.py", line 12, in test_communicate
    r = p.communicate(b'uname -a', timeout=1)
  File "C:\Root\python\3.10.11\lib\subprocess.py", line 1173, in communicate
    sts = self.wait(timeout=self._remaining_time(endtime))
  File "C:\Root\python\virtualzone\tech310\lib\site-packages\eventlet\green\subprocess.py", line 90, in wait
    raise TimeoutExpired(self.args, timeout)
subprocess.TimeoutExpired: Command '['cmd']' timed out after -94.06300000002375 seconds
----------------------------------------------------------------------
Ran 2 tests in 95.104s
FAILED (errors=1)

if Ctrl+C pressed during the state of block, and kill cmd.exe, output would change to:

Exception in thread Thread-1 (_readerthread):                                   
Traceback (most recent call last):                                              
  File "C:\Root\python\3.10.11\lib\threading.py", line 1016, in _bootstrap_inner
    self.run()                                                                  
  File "C:\Root\python\3.10.11\lib\threading.py", line 953, in run              
    self._target(*self._args, **self._kwargs)                                   
  File "C:\Root\python\3.10.11\lib\subprocess.py", line 1515, in _readerthread  
    buffer.append(fh.read())                                                    
KeyboardInterrupt                                                               
(None, b'')                                                                     
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant