# @file Test.py
# Requirement 1
def requirement1():
'''
Requirement 1:
The server will accept command line arguments of:
-a / --address <ip address> -IP address to listen on(default: all or default interface)
-p / --port <port> -Port to listen on(default: 12345)
'''
log = "Requirement 1:\n"
args1 = ["", "-a 127.0.0.1", "--address 127.0.0.1"]
args2 = ["", "-p 7777", "--port 7777"]
processName = f"..\exe\server.exe"
stdout.write(f" [•] {processName} {args1[2]} {args2[2]}\n")
someProcess = None
someProcess = subprocess.Popen([processName, args1[2], args2[2]], stdout = subprocess.PIPE)
sleep(1) # Wait for slow ass WiNdOws to get resources for the process
# If process failed to start
if someProcess is None:
log += f" [F] {processName} {args1[2]} {args2[2]}\n"
return log
lines = someProcess.stdout.readlines()
for line in lines:
line = cleanLine(line)
stdout.write(f"{line}\n")
if "ERROR" in line:
log += f" [F] {processName} {args1[2]} {args2[2]}\n"
elif "ready" in line:
log += f" [P] {processName} {args1[2]} {args2[2]}\n"
else:
continue
someProcess.kill()
return log
I am doing a unit test on a server I wrote myself: Client; start, ask for input, send string to server, wait up to 1 second for server to reply with same string, or time out after 1 second. Close client. Server; start, wait for connection, return string given, wait for connection until user sends Ctrl+C in Command Prompt.
While testing server.exe:
If I someProcess = subprocess.Popen([processName, args1[2], args2[2]], stdout = subprocess.PIPE)
after restarting my Windows10 machine, lines = someProcess.stdout.readlines()
will work as expected and the rest of the script runs just fine grabbing the lines from the stdout of the spawned process from Popen().
However, when I force quit via a Ctrl+C keyboard interrupt in the Command Prompt running my Test.py script, the NEXT time (and every time after) I run my script lines = someProcess.stdout.readlines()
will hang.
Measures I've taken to investigate and try and clear this:
Restarted machine and placed everything for the someProcess variable in a context manager like with subprocess.Popen([processName, args1[2], args2[2]], stdout = subprocess.PIPE) as someProcess:
thinking that with
would control all resources and clean up for me should the Test.py script quit in ANY manner. Run the script, force quit, can't rerun the scritp without the same problem occurring. Turns out with
doesn't clean up well. (So is this Python failing to clean up after itself?)
I've gone to Task Manager and used ProcessExplorer to find the process started with Popen() and end that task/kill process. This however does not allow me to rerun the script with intended results. The readlines()
call still hangs. I have to restart my entire machine. (So is this Windows failing to clean up ALL resources after a process exits ungracefully?)
Ok, maybe the port is stuck? Lets do netstat -ano
real quick. Nope, no port being used by zombies or PIDs that my script started. Also, the server would throw the appropriate WSA error: 10048 and I would know that the port I told it to bind()
to is taken. Regardless, someProcess.stdout.readlines()
should get that error from the spawned process and then print to the Test.py stdout the server's 10048 error. However, readlines()
hangs and never returns.
What I think is happening:
someProcess.stdout.readlines()
and is blocked endlessly waiting for something to read. However, there is nothing to read because the stream,pipe for the someProcess
THIS run and EVERY run after force quitting Test.py is broken?QUESTION: How do I make sure that whenever I call ```subprocess.Popen()```` it will return a process with which I can safely work with? Regardless of previous runs of Test.py and how it was terminated.
A thorough read of this https://bugs.python.org/issue43346 and a lengthy conversation with my colleague has satisfied my question.
Long story short: subprocess.run()
and subprocess.Popen()
have known blocking issues when threads close on Windows systems and is being tracked by Python.org.