views:

925

answers:

4

According to wikipedia ( http://en.wikipedia.org/wiki/Fork_bomb ), the forkbomb ":(){ :|:& };:" can be stopped with the zsh command "while (sleep 100 &!) do; done", which will supposedly spawn sleep 100 processes until all the forkbomb processes are gone. This seems like magic to me. Can anybody explain why/how this works? I'm especially curious as to exactly what "&!" is doing there.

Follow up question: what would an equivalent command look like in bash?

+2  A: 

Very interesting question!

According to that Wikipedia article, the purpose of the complete command is to create many harmless jobs that will disable the fork bomb because it will no longer able to spawn even more children.

According to the zsh manual,

If a job is started with &|' or &!', then that job is immediately disowned. After startup, it does not have a place in the job table, and is not subject to the job control features described here.

I am not sure how to achieve the same with bash. However, something like the following might do:

nohup sleep 100 &
innaM
+4  A: 

First the fork bomb can be written:

foo()
{
    foo|foo&
}
foo

Which makes it a little clearer - each iteration starts two subprocesses, then dies. So if the forking fails, it won't hang around.

Therefore all we have to do is make the forking temporarily fail. Thus we create processes that sleep 100 and occupy process space, as the sleep processes do.

The zsh &! is like & but disowns the new process (doesn't kill it at logoff) - it's probably not important in this example. (manual) It can be replaced with nohup.

Therefore the bash:

while (nohup sleep 100 &) do; done

should work.

Douglas Leeder
+3  A: 

The reason that a fork-bomb works is because there is a finite limit to the number of processes that can be running at any one time, and a fork-bomb is designed to fill this limit.

Because the forkbomb code you provided dies if it cannot spawn a child process, the parent processes do not actually hang around, but the fact that the children keep creating new grand*-children keeps the process table full.

So the sleep solution is designed to sneak in some processes that just sleep for a short period of time, and for each sleep process that manages to be created, there are less fork-bombs happening. Eventually the sleep processes fill up the proces table themselves and the fork bombs die off.

Once the process table is full off sleep processes the while loop can be killed, and the sleep processes will die once their sleep time is up. Problem solved.

As has already been mentioned the important part of the zsh command is the run-in-background &, so the bash command would basically be the same as given in the other answers:

while (sleep 100 &) do; done

I don't think that the nohup/! part is important unless you want to log out within the sleep time, but I'd be happy to be set straight if I am wrong.

David Dean
A: 

Hi guys, I'm the guy who wrote that part of the Wikipedia article (and who "discovered" this cure after accidentally starting the fork bomb on my system!).

The reason for the "&!" instead of "&" is indeed to prevent zsh from doing job-control over the new process, i.e., trying to care when and if it finished. I don't remember exactly why job control was a problem when I tried it, but it was. You can actually try it to see how the "cure" works and what happens if you don't prevent job control. Maybe the problem with job control had to do with some bug in zsh that doesn't even exist in bash, and maybe it is no longer relevant in zsh either.

So try just an "&" with bash, and if job control is interfering, try to disable it ("set +m") and hopefully this would work.

You're right that the wikipedia article should probably not be zsh dependent.

Nadav Harel