Lab: Fork Bomb

Lab: Fork Bomb

Short Description

The purpose of this lab is to demonstrate how a simple programmer error can impact the availability of a computing resource.

Goals

The goals of this lab are to help you understand

The Lab

  1. Boot any of your images and log in as any user.
  2. Start at least two terminals.
    • We will use one to edit code.
    • In the other run the top command.
    • You may want a third terminal for compiling.
  3. Create a space to work.
    • Make a directory called forkCode
    • In the editing terminal, change to this directory.
  4. Download the basic program that runs a long computation.
    • Download start.cpp
    • Download Makefile
    • Place these two files in your working directory.
    • Look at start.cpp.
      • This is just a program that will run a long time.
    • Compile and run this program.
      • Note what happens to the load average in the window running top.
      • Note that you can "see" the process in the window running top.
    • I made a copy of start.cpp called working.cpp
      • cp start.cpp working.cpp
      • Add working to the OBJS line in the Makefile
  5. Print the process id.
    • On a unix system, each process has an associated process id (PID).
    • You can get a process id with a call to getpid
      • pid_t getpid(void);
    • We will use this to keep track of processes.
    • Get and print the process id in working.cpp
      • Add the following to your code:
      • pid_t myPid;
        
           myPid = getpid();
           cout << "My pid is " << myPid << endl; 
    • compile and run this code.
    • Note that the process id printed by the program should match the process id in top.
  6. The fork command
    • Fork creates a copy of the program with a few difference
      • One use of this is to write a parallel program.
      • We will simulate that here.
    • The most important is the pid.
      • The value returned to the original program is the pid of the new program.
      • The new program has a return value of 0.
    • In Operating Systems we discuss other differences.
    • pid_t fork(void);
    • After fork is called, there are two copies of the program running.
    • Modify working.cpp
      • pid_t myPid;
           pid_t pid;
        
           pid = fork();
           myPid = getpid();
           if (pid == 0) {
              cout << "Child here, my pid is " << myPid << endl;
           } else {
              cout << "Parent here, my pid is " << myPid << endl;
           }
        
           for(i = 0; i < 10'000; ++i) {
    • Compile and run this.
      • Notice now there are two copies of working running.
      • Notice the pid's match
      • Notice that the load goes up
    • Since the two programs can end in any order you
      • Will have the prompt returned.
      • But it may have some output after from the child process.
  7. But I want a program that runs 10 copies not 1.
    • No problem, let's add a loop to start forking our processes.
      • For an experienced programmer, this is a warning situation.
      • If we are not careful we will kill the system.
      • Caution: placing a fork inside of a loop can lead to a fork bomb.
    • Let's do it correctly first.
      • const int PROCS{10};
        
        ....
        pid_t pid;
        
        i = 0;  
        while (i < PROCS) {
             pid = fork();
             myPid = getpid();
        
             if (pid == 0) {
                cout <<"Child here, my pid is " << myPid <<endl;
                i = PROCS;
             } else {
                cout << "Parent here, my pid is " << myPid << endl;
                i++;
             }
        }
      • Note, the child will set i so that it immediately exits from the loop.
      • The parent will increment i so that it starts i children with fork.
    • Save this, compile it and run it.
      • What happens to the load?
      • Do you see 10 processes running?
      • Note, if you kill the parent with ctrl-c the other process will terminate as well.
        • There are ways to change this so it does not happen.
    • Look over the code and make sure you understand what is happening.
  8. Create the fork bomb.
    • Comment out the line i = PROCS; in the child branch of the if.
    • Recompile and run the code.
    • Watch the load increase
    • In another window, try to run a command. What happens?
    • What is happening?
    • Note, you are lucky, you can kill the fork bomb by typing ctrl-c in the window where you started it.
      • This is not the case when someone else starts one.
  9. Defending against a fork bomb
    • On a linux system you can defend against a fork bomb by setting a limit in /etc/security/limits.conf
    • Add a line at the end
    • You will need to do this as root
       bob     hard    nproc   150 
    • This only takes effect on login so log out and back in again.
    • This will set a hard limit for bob, so if you want to run top, do so before you start the fork bomb.
    • Or better yet, log in as alice and su to bob in one window and run the fork bomb.