Python running as Windows Service: OSError: [WinError 6] The handle is invalid
Asked Answered
N

3

29

I have a Python script, which is running as a Windows Service. The script forks another process with:

with subprocess.Popen( args=[self.exec_path], stdout=subprocess.PIPE, stderr=subprocess.STDOUT) as proc:

which causes the following error:

OSError: [WinError 6] The handle is invalid
   File "C:\Program Files (x86)\Python35-32\lib\subprocess.py", line 911, in __init__
   File "C:\Program Files (x86)\Python35-32\lib\subprocess.py", line 1117, in _get_handles
Nonappearance answered 18/10, 2016 at 12:51 Comment(0)
N
44

Line 1117 in subprocess.py is:

p2cread = _winapi.GetStdHandle(_winapi.STD_INPUT_HANDLE)

which made me suspect that service processes do not have a STDIN associated with them (TBC)

This troublesome code can be avoided by supplying a file or null device as the stdin argument to popen.

In Python 3.x, you can simply pass stdin=subprocess.DEVNULL. E.g.

subprocess.Popen( args=[self.exec_path], stdout=subprocess.PIPE, stderr=subprocess.STDOUT, stdin=subprocess.DEVNULL)

In Python 2.x, you need to get a filehandler to null, then pass that to popen:

devnull = open(os.devnull, 'wb')
subprocess.Popen( args=[self.exec_path], stdout=subprocess.PIPE, stderr=subprocess.STDOUT, stdin=devnull)
Nonappearance answered 18/10, 2016 at 12:51 Comment(13)
Service executables (e.g. pythonservice.exe) are run detached (i.e. not attached to an instance of conhost.exe), in which case GetStdHandle should return NULL, not INVALID_HANDLE_VALUE.Calandra
A similar error is common when running via pythonw.exe. Prior to Windows 8, a pythonw.exe process has console handle values in its standard handles, but they're invalid since there's no attached console. subprocess raises an error when it tries to call DuplicateHandle on the invalid handle.Calandra
Ok, I think I have the edgiest of edge cases here, so I'm not sure anyone else will find it - My script has been compiled into a standalone .exe using PyInstaller. The script isn't the actual service - a C#/.net app is the service which forks the standalone .exe. The service has a standalone mode, which, when executed as a desktop user, works as expected.Nonappearance
Thanks for the help, I had a few dependency python packages which broke after configuring application to run as a Windows Service - same issue and workaround used to fix.Erickson
similar error comes in Python 3.6 for subprocess.run( cmd, stdout = subprocess.PIPE, stderr = subprocess.PIPE) when running inside nested (subprocess.Popen, Windows Application, python via DLL). adding stdin = subprocess.DEVNULL fixed it.Neau
Ran into the same issue after I packaged a script with Pyinstaller. Using subprocess.DEVNULL did the trick. Big thanks !Serigraph
Stupid question, but you set stdin as DEVNULL in the original subprocesses module, or in the erroneous script that calls subprocesses ? If it is the first - can you tell me where to find it exactly? If it is the second - I tried adding it as keyword argument in the subprocess.Popen, as well as in the subprocess.call line (where the error actually happens), using kwargs['stdin'] = devnull, but it doesn't solve the problem. :(Hazlett
@Isquare1 you only need to fix your code (or 3rd party code), not Python's codebase.Nonappearance
Dude, you saved me! Run on this problem like this: Popen(['ping', '192.168.0.1'], stdout=PIPE, stderr=PIPE). Seems you had to support stdin if you supported stdout and stderr.Aerothermodynamics
Hey @SmitJohnth. Top tip, use native Python libraries, like pypi.org/project/icmplib, where you can. It's more powerful and you'll find it much easier to handle errors.Nonappearance
@AlastairMcCormack Can it report while working? The call simply blocked for me.Aerothermodynamics
@SmitJohnth looks like it has a count option. Set it to 1 and loop.Nonappearance
@AlastairMcCormack well... I almost already written this using subprocess. And this lib requires root. I'll still need subprocess at some time.Aerothermodynamics
V
3

Add stdin=subprocess.PIPE like:

with subprocess.Popen( args=[self.exec_path], stdout=subprocess.PIPE, stdin=subprocess.PIPE, stderr=subprocess.STDOUT) as proc:
Virnelli answered 21/6, 2017 at 16:23 Comment(0)
S
-1

In my version of subprocess.py the issue was on line 1348 where conan choked on...

p2cread = _winapi.GetStdHandle(_winapi.STD_INPUT_HANDLE)

Solution was to change that line to: p2cread = None

The next lines after that were:

                if p2cread is None:
                    p2cread, _ = _winapi.CreatePipe(None, 0)
                    p2cread = Handle(p2cread)
                    err_close_fds.append(p2cread)
                    _winapi.CloseHandle(_)
Scipio answered 20/12, 2023 at 22:29 Comment(1)
That's not a very maintainable way of fixing the problem - it'll only work on your PC. So you'll have to modify every machine your code runs on and repatch everytime you upgrade Python. Hopefully the existing answers will show you how to fix your code to handle the problem.Nonappearance

© 2022 - 2024 — McMap. All rights reserved.