diff --git a/README.md b/README.md
index f224b04..c272d09 100644
--- a/README.md
+++ b/README.md
@@ -186,7 +186,8 @@ then just `pip install dumb-init`.
## Usage
Once installed inside your Docker container, simply prefix your commands with
-`dumb-init`.
+`dumb-init` (and make sure that you're using [the recommended JSON
+syntax][docker-cmd-json]).
Within a Dockerfile, it's a good practice to use dumb-init as your container's
entrypoint. An "entrypoint" is a partial command that gets prepended to your
@@ -209,6 +210,10 @@ Running this same command without `dumb-init` would result in being unable to
stop the container without `SIGKILL`, but with `dumb-init`, you can send it
more humane signals like `SIGTERM`.
+It's important that you use [the JSON syntax][docker-cmd-json] for `CMD` and
+`ENTRYPOINT`. Otherwise, Docker invokes a shell to run your command, resulting
+in the shell as PID 1 instead of dumb-init.
+
## Building dumb-init
@@ -255,3 +260,4 @@ your machine.
[systemd]: https://wiki.freedesktop.org/www/Software/systemd/
[sysvinit]: https://wiki.archlinux.org/index.php/SysVinit
[docker]: https://www.docker.com/
+[docker-cmd-json]: https://docs.docker.com/engine/reference/builder/#run
diff --git a/testing/__init__.py b/testing/__init__.py
index ef2d543..1d87f30 100644
--- a/testing/__init__.py
+++ b/testing/__init__.py
@@ -50,14 +50,17 @@ def child_pids(pid):
"""Return a list of direct child PIDs for the given PID."""
children = set()
for p in LocalPath('/proc').listdir():
- stat = p.join('stat')
- if stat.isfile():
- stat = stat.open().read()
- m = re.match('^\d+ \([^\)]+\) [a-zA-Z] (\d+) ', stat)
+ try:
+ stat = open(p.join('stat').strpath).read()
+ m = re.match('^\d+ \(.+?\) [a-zA-Z] (\d+) ', stat)
assert m, stat
ppid = int(m.group(1))
if ppid == pid:
children.add(int(p.basename))
+ except IOError:
+ # Happens when the process exits after listing it, or between
+ # opening stat and reading it.
+ pass
return children
diff --git a/tests/exit_status_test.py b/tests/exit_status_test.py
index bb7be1d..f67a17c 100644
--- a/tests/exit_status_test.py
+++ b/tests/exit_status_test.py
@@ -1,4 +1,5 @@
import signal
+import sys
from subprocess import Popen
import pytest
@@ -17,7 +18,7 @@ def test_exit_status_regular_exit(exit_status):
@pytest.mark.parametrize('signal', [
signal.SIGTERM,
- signal.SIGINT,
+ signal.SIGHUP,
signal.SIGQUIT,
signal.SIGKILL,
])
@@ -26,6 +27,10 @@ def test_exit_status_terminated_by_signal(signal):
"""dumb-init should exit with status 128 + signal when the child process is
terminated by a signal.
"""
- proc = Popen(('dumb-init', 'sh', '-c', 'kill -{0} $$'.format(signal)))
+ # We use Python because sh is "dash" on Debian and "bash" on others.
+ # https://github.com/Yelp/dumb-init/issues/115
+ proc = Popen(('dumb-init', sys.executable, '-c', 'import os; os.kill(os.getpid(), {0})'.format(
+ signal,
+ )))
proc.wait()
assert proc.returncode == 128 + signal