fork                  package:fork                  R Documentation

_C_r_e_a_t_e _a _n_e_w _R _p_r_o_c_e_s_s _u_s_i_n_g _t_h_e _U_n_i_x '_f_o_r_k' _s_y_s_t_e_m _c_a_l_l

_D_e_s_c_r_i_p_t_i_o_n:

     Create a new R process using the Unix 'fork' system call.

_U_s_a_g_e:

     fork(slave)

_A_r_g_u_m_e_n_t_s:

   slave: Function to be executed in the new R process. This can be
          'NULL', see details.

_D_e_t_a_i_l_s:

     This function provides a thin wrapper around the Unix "fork"
     system call, which will create a new process which is an exact
     copy of the current R process, including open files and sockets
     including STDIN and STDOUT.

     The 'child' parameter should  normally contain a function to be
     executed in the newly created process.  This function will be
     called in the new process, and 'exit()' will be called when it
     returns to terminate the process.

     If you wish to explicitly control what happens in the child
     process, you can pass 'child=NULL', in which case you are
     responsible for managing all the details.

     First, the child process must call 'exit()' to terminate instead
     of 'quit'.  This is necessary to ensure that temporary files or
     directories created by the parent process are not removed by the
     child.

     Second, the child process should not attempt to use STDIN to
     obtain commands since it shares all files open at the time of the
     fork with the parent.  This includes STDIN, consequently, any code
     following the fork will be be obtained *competitively* by both
     processes.  This usually means that neither process will get a
     consistent picture of the following commands, since which process
     gets each line will be simply a matter of which process asked
     first.

     The best way to avoid the second problem is to simply pass a
     function to 'fork' using the 'slave' parameter.  Another way to
     accomplish this is to ensure that all code that needs to be
     executed has already been fed to the interpreter before the fork
     call occurs. The simplest mechinism to achieve this is to wrap the
     code containing the fork in a code block using curly brackets ('{
     ... }'). This can be a top-level code block, or can be withing a
     loop or function call.,

     To illustrate, this code is a familiar C idiom for forking will
     NOT be interpreted properly:


       pid = fork(slave=NULL)

       if(pid==0) { 

         cat("Hi from the child process"); exit() 

       } else { 

         cat("Hi from the parent process"); 

       }

     On the other hand, wrapping this code with curly brackets ensures
     it IS intepreted properly:


       {
         pid = fork(slave=NULL) 
         if(pid==0) { 
           cat("Hi from the child process\n"); exit() 
         } else {
           cat("Hi from the parent process\n");
         } 
       }

     .

_V_a_l_u_e:

     This function returns the process ID of the child process to the
     parent process.  If 'slave' is 'NULL' the function returns 0 to
     the  child  process.

_A_u_t_h_o_r(_s):

     Gregory R. Warnes gregory_r_warnes\@groton.pfizer.com

_R_e_f_e_r_e_n_c_e_s:

     'fork' man page

_S_e_e _A_l_s_o:

     'getpid', 'exit', 'wait', 'kill', 'killall'

_E_x_a_m_p_l_e_s:

     ###
     # Count from 1 to 10 in a separate process
     ###

     # define the function to do the work
     testfun <- function()
       {
         cat("Counting in process", getpid(), "\n")
         for(i in 1:10)
           {
             i <<- i+1  # assign into Global environment
             cat("i=",i,"\n")
           }
         cat("Done counting in process", getpid(), "\n")
       }

     # run normally, the function will change our value of i
     i <- 0
     testfun()
     i 

     # Run in a separate process, our value of i remains unchanged
     i <- 0
     {
       pid <- fork(testfun)
       wait(pid) # wait until the child finishes, then display its exit status
     }
      

     ###
     # Use a socket to communicate between two processes.  Information
     # typed on the console, which is read by the initial process, will be send
     # to the child process for display. 
     ###
     ## Not run: 
     send <- function()
       {
          pid <- getpid()
          con1 <- socketConnection(Sys.info()["nodename"], port = 6011)
          i <- 1
          while(TRUE)
            {
              cat("[",pid,"] ",i,": ",sep="")
              data <- readLines(stdin(), n=1)
              writeLines(data, con=con1)
              if( length(grep("quit", data))>0 )
                 break;
              i <- i+1
            }
          close(con1)
       }

     recieve <- function()
       {
          pid <- getpid()
          con2 <- socketConnection(port = 6011, block=TRUE, server=TRUE)
          i <- 1
          while(TRUE)
            {
               data <- readLines(con2, n=1)
               cat("[",pid,"] ",i,": ",sep="")
               writeLines(data, stdout())
               if( length(grep("quit", data))>0 )
                   break;
               i <- i+1
            }
          close(con2)
       }

     pid <- fork(recieve)
     send()
     ## End(Not run)

