15

After going through the famous Fork Bomb questions on Askubuntu and many other Stack Exchange sites, I don't quite understand what everyone is saying like it's obvious.

Many answers (Best example) say this:

"{:|: &} means run the function : and send its output to the : function again "

Well, what exactly is the output of : ? What is being passed to the other :?

And also:

Essentially you are creating a function that calls itself twice every call and doesn't have any way to terminate itself.

How exactly is that executed twice? In my opinion, nothing is passed to the second : until the first : finishes its execution, which actually will never end.

In C for example,

foo()
{
    foo();
    foo(); // never executed 
}

the second foo() is not executed at all, just because the first foo() never ends.

I am thinking that the same logic applies to :(){ :|: & };: and

:(){ : & };:

does the same job as

:(){ :|: & };:

Please help me understand the logic.

  • 9
    Command in pipelines run in parallel, in :|:, the second : does not need to wait the first one completed. – cuonglm Oct 16 '16 at 17:45
26

Piping doesn't require that the first instance finishes before the other one starts. Actually, all it is really doing is redirecting the stdout of the first instance to the stdin of the second one, so they can be running simultaneously (as they have to for the fork bomb to work).

Well, What exactly is the output of : ? what is being passed to the other : ?

':' is not writing anything to the other ':' instance, it's just redirecting the stdout to the stdin of the second instance. If it writes something during its execution (which it never will, since it does nothing but forking itself) it would go to the stdin of the other instance.

It helps to imagine stdin and stdout as a pile:

Whatever is written to the stdin will be piled up ready for when the program decides to read from it, while the stdout works the same way: a pile you can write to, so other programs can read from it when they want to.

That way it's easy to imagine situations like a pipe that has no communication happening (two empty piles) or non-synchronized writes and reads.

How exactly is that executed twice? In my opinion, nothing is passed to the second : until the first : finishes its execution, which actually will never end.

Since we are just redirecting the input and output of the instances, there is no requirement for the first instance to finish before the second one starts. It's actually usually desired that both run simultaneously so the second can work with the data being parsed by the first one on the fly. That's what happens here, both will be called without needing to wait for the first to finish. That applies to all pipe chains lines of commands.

I am thinking that the same logic applies to :(){ :|: & };: and

:(){ : & };:

Does the same job as

:(){ :|: & };:

The first one wouldn't work, because even though it's running itself recursively, the function is being called in the background (: &). The first : doesn't wait until the "child" : returns before ending itself, so in the end you'd probably only have one instance of : running. If you had :(){ : };: it would work though, since the first : would wait for the "child" : to return, which would wait for its own "child" : to return, and so on.

Here's how different commands would look like in terms of how many instances would be running:

:(){ : & };:

1 instance (calls : and quits) -> 1 instance (calls : and quits) -> 1 instance (calls : and quits) -> 1 instance -> ...

:(){ :|: &};:

1 instance (calls 2 :'s and quits) -> 2 instances (each one calls 2 :'s and quits) -> 4 instances (each one calls 2 :'s and quits) -> 8 instances -> ...

:(){ : };:

1 instance (calls : and waits for it to return) -> 2 instances (child calls another : and waits for it to return) -> 3 instances (child calls another : and waits for it to return) -> 4 instances -> ...

:(){ :|: };:

1 instance (calls 2 :'s and waits for them to return) -> 3 instances (children calls 2 :'s each and wait for them to return) -> 7 instances (children calls 2 :'s each and wait for them to return) -> 15 instances -> ...

As you can see, calling the function in the background (using &) actually slows the fork bomb, because the callee will quit before the called functions returns.

  • Question. Would :(){ : & && : &}; : also work as a fork bomb? You would also increase exponentially, and, in fact, you could put multiple : & 's in there to increase it even faster. – JFA Oct 17 '16 at 6:40
  • @JFA ` ─> $ :(){ : & && : &}; :` gives syntax error bash: syntax error near unexpected token &&' . You could do this : :(){ $(: &) && $(: &)}; : , But again, unlike pipeline, that won't run parallel. Which would be equivalent of :(){: & };: . Like to verify ? try these time $( $(sleep 1 & ) && $(sleep 1 &) ) and this time $(sleep 1 | sleep 1) – Severus Tux Oct 17 '16 at 10:01
  • Exactly, the :(){ $(: &) && $(: &)}; is a function that is issuing a logical AND operation in the return values of the first and second instance. The problem is, since a logical AND is only true if both values are true, for efficiency only the first instance will be run. If its return value is 1 it then the second instance will run. If you want to make the fork bomb even faster I think you could just pipe more instances into the chain, like :(){ :|:|: &}; : – IanC Oct 17 '16 at 13:43
  • Just as a side note, many scripts use this behaviour of AND in the following situation: Say you want to run prog2 if prog1 returns true (which in bash is 0). Instead of doing a if-statement ( if [ prog1 ]; then; prog2; fi ) you could just write (prog1 && prog2), and prog2 would only run if the return value of prog1 was true. – IanC Oct 17 '16 at 13:52
  • Ok, these are all great points. I use && to call apt-get update && apt-get upgrade, and & at the end of the line to run in the background, but that' s a great point that they won't work together. A semicolon also does not work with the ampersand. – JFA Oct 17 '16 at 15:20

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.