Popen.wait never returning with docker-compose
Question:
I am developing a wrapper around docker compose with python.
However, I struggle with Popen.
Here is how I launch launch it :
import subprocess as sp
argList=['docker-compose', 'up']
env={'HOME': '/home/me/somewhere'}
p = sp.Popen(argList, env=env)
def handler(signum, frame):
p.send_signal(signum)
for s in (signal.SIGINT,):
signal.signal(s, handler) # to redirect Ctrl+C
p.wait()
Everything works fine, when I hit Ctrl+C, docker-compose kills gracelly the container, however, p.wait()
never returns…
Any hint ?
NOTE : While writing the question, I though I needed to check if p.wait()
does actually return and if the block is after (it’s the last instruction in the script). Adding a print after it end in the process exiting normally, any further hints on this behavior ?
Answers:
When I run your code as written, it works as intended in that it causes docker-compose
to exit and then p.wait()
returns. However, I occasionally see this behavior:
Killing example_service_1 ... done
ERROR: 2
I think that your code may end up delivering SIGINT
twice to docker-compose
. That is, I think docker-compose
receives an initial SIGINT
when you type CTRL-C
, because it has the same controlling terminal as your Python script, and then you explicitly deliver another SIGINT
in your handler
function.
I don’t always see this behavior, so it’s possible my explanation is incorrect.
In any case, I think the correct solution here is imply to ignore SIGINT
in your Python code:
import signal
import subprocess
argList = ["docker-compose", "up"]
p = subprocess.Popen(argList)
signal.signal(signal.SIGINT, signal.SIG_IGN) # to redirect Ctrl+C
p.wait()
With this implementation, your Python code ignores the SIGINT
generated by CTRL-C
, but it is received and processed normally by docker-compose
.
I am developing a wrapper around docker compose with python.
However, I struggle with Popen.
Here is how I launch launch it :
import subprocess as sp
argList=['docker-compose', 'up']
env={'HOME': '/home/me/somewhere'}
p = sp.Popen(argList, env=env)
def handler(signum, frame):
p.send_signal(signum)
for s in (signal.SIGINT,):
signal.signal(s, handler) # to redirect Ctrl+C
p.wait()
Everything works fine, when I hit Ctrl+C, docker-compose kills gracelly the container, however, p.wait()
never returns…
Any hint ?
NOTE : While writing the question, I though I needed to check if p.wait()
does actually return and if the block is after (it’s the last instruction in the script). Adding a print after it end in the process exiting normally, any further hints on this behavior ?
When I run your code as written, it works as intended in that it causes docker-compose
to exit and then p.wait()
returns. However, I occasionally see this behavior:
Killing example_service_1 ... done
ERROR: 2
I think that your code may end up delivering SIGINT
twice to docker-compose
. That is, I think docker-compose
receives an initial SIGINT
when you type CTRL-C
, because it has the same controlling terminal as your Python script, and then you explicitly deliver another SIGINT
in your handler
function.
I don’t always see this behavior, so it’s possible my explanation is incorrect.
In any case, I think the correct solution here is imply to ignore SIGINT
in your Python code:
import signal
import subprocess
argList = ["docker-compose", "up"]
p = subprocess.Popen(argList)
signal.signal(signal.SIGINT, signal.SIG_IGN) # to redirect Ctrl+C
p.wait()
With this implementation, your Python code ignores the SIGINT
generated by CTRL-C
, but it is received and processed normally by docker-compose
.