How can I reproduce zombie process with bash as PID1 in docker?
I also wanted to verify if my jenkins container slaves can generate zombies or not.
Since my images run the scl
binary which in turn starts the java JLNP client, I performed the following in jenkins slave groovy script console:
def process=new ProcessBuilder("bash", '-c', 'sleep 10 </dev/null &>/dev/null & disown').redirectErrorStream(true).start()println process.inputStream.textprintln " ps -ef".execute().text
Zombies have been generated. That is with scl
ending up as PID 1.
Then I looked at your question and decided to try out bash. My first attempt was changing ENTRYPOINT to this:
bash -c "/usr/bin/scl enable rh-ror42 -- /usr/local/bin/run-jnlp-client $1 $2" --
Then looking at ps
output I realized that PID 1 was not bash
but in fact PID 1 was still the scl
binary. Finally changed command to:
bash -c "/usr/bin/scl enable rh-ror42 -- /usr/local/bin/run-jnlp-client $1 $2 ; ls" --
That is adding some random second command after the scl
command. And voila - bash became PID 1 and no zombies generate anymore.
Looking at your example, I see that you run bash -c
with more than one command. So in your test bed, you are running something like my last command. But in your work containers, it is likely that you run bash -c
with only one command and it appears bash
became clever enough to effectively do an exec
. And probably in your work containers that generate zombies, bash
is not actually PID 1 contrary to what you expect.
Perhaps you can ps -ef
inside your existing work containers and verify if my guess is correct.
I hit the same problem while attempting to create a zombie process inside a container with bash
as PID 1. Turns out (as you can see from the wait4()
calls), that bash
actually is waiting on all children in a tight loop (man wait
explains that waiting on -1
will return when any child exits).
This means when an orphan is reparented to bash
, bash
will correctly wait
on it to prevent it from remaining a zombie. Very strange that all literature on the internet says otherwise.
To test if your applications are leaving zombies, you will need to assure that bash
is not PID 1, rather it's the first child of PID 1.
On another question How to reap zombie process in docker container with bash I had shown example how to create a container with bash
that will ignore the zombie processes by becoming PID 1 and executing bash
as a child. Here is c
code that can be used to generate the container:
#include <stdlib.h>int main() { int status; status = system("/bin/bash");}
The code that generates the zombie and the dockerfile for the container can be found in the github repository
After compiling the module in an image, all you need to do is to start the container with docker run -ti --rm image /zombie/ignore
and you will get the bash
as a first child. To see this working in practice, check the link to the other question.
root@1bd66ac87f0a:/zombie# ps -eaf --forestUID PID PPID C STIME TTY TIME CMDroot 1 0 0 11:17 pts/0 00:00:00 /zombie/ignoreroot 7 1 0 11:17 pts/0 00:00:00 sh -c /bin/bash