Fork: Difference between revisions

From Rosetta Code
Content added Content deleted
({{omit from|PARI/GP}})
m (→‎{{header|Tcl}}: Rewrote for clarity ()
Line 407: Line 407:
Fork is one of the primitives used for process creation in Unixy systems. It creates a copy of the process that calls it, and the only difference in internal state between the original and the copy is in the return value from the fork call (0 in the copy, but the pid of the copy in the parent).
Fork is one of the primitives used for process creation in Unixy systems. It creates a copy of the process that calls it, and the only difference in internal state between the original and the copy is in the return value from the fork call (0 in the copy, but the pid of the copy in the parent).


The {{libheader|Expect}}package includes a fork. So does the {{libheader|TclX}}package.
The [[SMW::off]][[:Category:Expect|Expect]][[Category:Expect]][[SMW::on]]{{#set:Uses library=Expect}}<!--{{libheader|Expect}}--> package includes a fork. So does the [[SMW::off]][[:Category:TclX|TclX]][[Category:TclX]][[SMW::on]]{{#set:Uses library=TclX}}<!--{{libheader|TclX}}--> package.


Example:
Example:

Revision as of 13:54, 5 November 2010

Task
Fork
You are encouraged to solve this task according to the task description, using any language you may know.

In this task, the goal is to spawn a new process which can run simultaneously with, and independently of, the original parent process.

Ada

Library: POSIX

<lang ada>with Ada.Text_IO,

    POSIX.Process_Identification,
    POSIX.Unsafe_Process_Primitives;

procedure Fork is

  use Ada.Text_IO,
      POSIX.Process_Identification,
      POSIX.Unsafe_Process_Primitives;

begin

  if Fork = Null_Process_ID then
     Put_Line ("This is the new process.");
  else
     Put_Line ("This is the original process.");
  end if;

exception

  when others =>
     Put_Line ("Something went wrong.");

end Fork;</lang>

Aikido

<lang aikido>

   var pid = fork()
   switch (pid) {
   case <0:
       println ("fork error")
       break
   case 0:
       println ("child")
       break
   default:
       println ("parent")
       break
   }

</lang>

ALGOL 68

Translation of: C
Works with: ALGOL 68G version Any - tested with release mk15-0.8b.fc9 - "fork" is not part of the standard's prelude.

<lang algol68>main: (

 INT pid;
 IF (pid:=fork)=0 THEN
   print("This is new process")
 ELIF pid>0 THEN
   print("This is the original process")
 ELSE
   print("ERROR: Something went wrong")
 FI

)</lang> Output:

This is new process
This is the original process

AutoHotkey

<lang autohotkey>MsgBox, 4, Fork, Start another process? IfMsgBox, Yes

   Run, %A_AhkPath% "%A_ScriptFullPath%"

MsgBox, 0, Fork, Stop this process.</lang>

Bash

<lang bash>(for ((i=0;i<10;i++)); do sleep 1; echo "Child process"; done) & for ((i=0;i<5;i++)); do

 sleep 2
 echo "Parent process"

done</lang>

C

Library: POSIX

<lang c>#include <stdio.h>

  1. include <stdlib.h>
  2. include <unistd.h>

int main() { pid_t pid;

if ((pid = fork()) == 0) { printf("child process\n"); } else if (pid > 0) { printf("parent process\n"); } else { perror("fork"); return EXIT_FAILURE; }

return EXIT_SUCCESS; }</lang>

C++

Translation of: C
Library: POSIX

<lang cpp>#include<iostream>

  1. include<unistd.h>

int main() {

 pid_t pid = fork();
 if (pid == 0)
 {
   std::cout << "This is the new process\n";
 }
 else if (pid > 0)
 {
   std::cout << "This is the original process\n";
 }
 else
 {
   std::cerr << "ERROR: Something went wrong\n";
 }
 return 0;

}</lang>

Clojure

Through its Java interop capabilities, Clojure has full access to the JRE's process creation and control facilities. The clojure.java.shell API (in Clojure 1.2; there's an equivalent in 1.1 clojure.contrib.shell) uses these facilities to provide a convenient way of running a shell command in a separate process, providing its arguments, input, environment, and working dir as necessary, and capturing the process's return code and its stdout and stderr output. <lang clojure>(require '[clojure.java.shell :as shell]) (shell/sh "echo" "foo") ; evaluates to {:exit 0, :out "foo\n", :err ""}</lang> Though this starts a separate process, the code in shell/sh blocks until the process completes. We can get other stuff done in the meantime by running the function in a separate thread with the core function future. Suppose we want to find files named "needle.*" in a large directory tree haystack, and do other stuff while the search proceeds. Using the Unix-like command find the code would look something like <lang clojure>(let [search (future (shell/sh "find" "." "-name" "needle.*" :dir haystack))]

 (while (and (other-stuff-to-do?) (not (future-done? search)))
   (do-other-stuff))
 (let [{:keys [exit out err]} @search]
   (if (zero? exit) 
     (do-something-with out)
     (report-errors-in err))))</lang>

Common Lisp

There's not a standard way to fork, but some implementations have built-in bindings for POSIX fork.

Translation of: C
Works with: SBCL

<lang lisp>(let ((pid (sb-posix:fork)))

 (cond
  ((zerop pid) (write-line "This is the new process."))
  ((plusp pid) (write-line "This is the original process."))
  (t           (error "Something went wrong while forking."))))</lang>

Erlang

<lang erlang>-module(fork). -export([start/0]).

start() ->

   spawn(fork,child,[]),
   io:format("This is the original process~n").

child() ->

   io:format("This is the new process~n").</lang>

Then you can compile your code and execute it:

<lang erlang>c(fork). fork:start().</lang>

Factor

This works only in the terminal, if used from the UI the child process won't print.

<lang factor>USING: unix unix.process ;

[ "Hello form child" print flush 0 _exit ] [ drop "Hi from parent" print flush ] with-fork</lang>

Haskell

<lang haskell>import System.Posix.Process

main = do

 forkProcess (putStrLn "This is the new process")
 putStrLn "This is the original process"</lang>

HicEst

<lang hicest>SYSTEM( RUN )

WRITE(Messagebox='?Y', IOStat=ios) "Another Fork?" IF(ios == 2) ALARM(999) ! quit immediately

! assume this script is stored as 'Fork.hic' SYSTEM(SHell='Fork.hic')

BEEP("c e g 'c") WRITE(Messagebox="!") "Waiting ..." ALARM(999)  ! quit immediately </lang>

Lua

Library: POSIX

<lang Lua>local posix = require 'posix'

local pid = posix.fork() if pid == 0 then

   print("child process")

elseif pid > 0 then

   print("parent process")

else

   error("unable to fork")

end</lang>

OCaml

<lang ocaml>#load "unix.cma";; let pid = Unix.fork ();; if pid > 0 then

 print_endline "This is the original process"

else

 print_endline "This is the new process";;</lang>

Oz

Mozart's support for distributed programming is quite unique. We can send code accross the network and share data by lexical scoping. It doesn't matter whether we create the process on the local machine (as in this example) or on some remote computer as long as we have ssh access (or some similar method) and Mozart is installed.

<lang oz>declare

 ParentVar1 = "parent data"
 ParentVar2
 functor RemoteCode
 export
    result:Result
 import QTk at 'x-oz://system/wp/QTk.ozf'
 define
    Result
    %% Show a simple window. When it is closed by the user, set Result.
    Window =
    {QTk.build
     td(action:proc {$} Result = 42 end %% on close
        label(text:"In child process: "#ParentVar1))} %% read parent process variable
    {Window show}
    !ParentVar2 = childData %% write to parent process variable
    {Wait Result}
 end
 %% create a new process on the same machine
 RM = {New Remote.manager init(host:localhost)}
 %% execute the code encapsulated in the given functor
 RemoteModule = {RM apply(RemoteCode $)}

in

 %% retrieve data from child process
 {Show RemoteModule.result} %% prints 42
 %% exit child process
 {RM close}
 {Show ParentVar2} %% print "childData"</lang>

Perl

Works with: Perl version 5.x

In the child code, you may have to re-open database handles and such.

<lang perl>FORK: if ($pid = fork()) {

   # parent code

} elsif (defined($pid)) {

   setsid; # tells apache to let go of this process and let it run solo
   # disconnect ourselves from input, output, and errors
   close(STDOUT);
   close(STDIN);
   close(STDERR);    
   # re-open to /dev/null to prevent irrelevant warn messages.
   open(STDOUT, '>/dev/null');
   open(STDIN, '>/dev/null');
   open(STDERR, '>>/home/virtual/logs/err.log');
   
   # child code
   
   exit; # important to exit

} elsif($! =~ /emporar/){

   warn '[' . localtime() . "] Failed to Fork - Will try again in 10 seconds.\n";
   sleep(10);
   goto FORK;

} else {

   warn '[' . localtime() . "] Unable to fork - $!";
   exit(0);

}</lang>

Obviously you could do a Fork in a lot less lines, but this code covers all the bases.

Another example using Proc::Fork module:

<lang perl>use Proc::Fork; run_fork {

   child {
       # child code ...
   }
   parent {
       # parent code ...
   }

};</lang>

Or: <lang perl>use Proc::Fork;

  1. parent code ...

run_fork {

   child {
       # child code ...
   }

};

  1. parent code continues ...</lang>

More complex example with retries and error handling: <lang perl>use Proc::Fork; run_fork {

   child {
       # child code ...
   }
   parent {
       # parent code ...
   }
   retry {
       # retry code ...
   }
   error {
       # error handling ...
   }

};</lang>

PHP

Translation of: C

<lang php><?php $pid = pcntl_fork(); if ($pid == 0)

 echo "This is the new process\n";

else if ($pid > 0)

 echo "This is the original process\n";

else

 echo "ERROR: Something went wrong\n";

?></lang>

PicoLisp

<lang PicoLisp>(unless (fork) # In child process

  (println *Pid)                      # Print the child's PID
  (bye) )                             # and terminate</lang>

PL/I

<lang PL/I> ATTACH SOLVE (X) THREAD (T5); </lang>

Pop11

<lang pop11>lvars ress; if sys_fork(false) ->> ress then

  ;;; parent
  printf(ress, 'Child pid = %p\n');

else

  printf('In child\n');

endif;</lang>

Python

Works with: Python version 2.5

<lang python>import os

pid = os.fork() if pid > 0:

# parent code

else:

# child code</lang>

Ruby

<lang ruby>pid = fork if pid

# parent code

else

# child code

end</lang> or <lang ruby>fork do

 # child code

end

  1. parent code</lang>

Slate

The following built-in method uses the cloneSystem primitive (which calls fork()) to fork code. The parent and the child both get a socket from a socketpair which they can use to communicate. The cloneSystem is currently unimplemented on windows (since there isn't a fork() system call).

<lang slate>p@(Process traits) forkAndDo: b [ | ret |

 ret: (lobby cloneSystem).
 ret first ifTrue: [p pipes addLast: ret second. ret second]
           ifFalse: [[p pipes clear. p pipes addLast: ret second. b applyWith: ret second] ensure: [lobby quit]]

].</lang>

Smalltalk

<lang smalltalk>'Here I am' displayNl. |a| a := [

 (Delay forSeconds: 2) wait . 
 1 to: 100 do: [ :i | i displayNl ]

] fork. 'Child will start after 2 seconds' displayNl. "wait to avoid terminating first the parent;

a better way should use semaphores"

(Delay forSeconds: 10) wait.</lang>

Standard ML

<lang sml>case Posix.Process.fork () of

  SOME pid => print "This is the original process\n"
| NONE     => print "This is the new process\n";</lang>

Tcl

(from the Tcl Wiki)

Fork is one of the primitives used for process creation in Unixy systems. It creates a copy of the process that calls it, and the only difference in internal state between the original and the copy is in the return value from the fork call (0 in the copy, but the pid of the copy in the parent).

The Expect package includes a fork. So does the TclX package.

Example:

<lang tcl>package require Expect

  1. or

package require Tclx

for {set i 0} {$i < 100} {incr i} {

   set pid [fork]
   switch $pid {
       -1 {
           puts "Fork attempt #$i failed."
       }
       0 {
           puts "I am child process #$i."
           exit
       }
       default {
           puts "The parent just spawned child process #$i."
       }
   }

}</lang>

In most cases though, one is not interested in spawning a copy of the process one already has, but rather wants a different process. When using POSIX APIs, this has to be done by first forking and then having the child use the exec system call to replace itself with a different program. The Tcl exec command does this fork&exec combination — in part because non-Unix OSs typicallly don't have "make a copy of parent process" as an intermediate step when spawning new processes.

Note that fork is only supported at all on unthreaded builds of Tcl. This is because the POSIX threads library does not sit well with the fork() system call.

Toka

<lang toka>needs shell getpid is-data PID [ fork getpid PID = [ ." Child PID: " . cr ] [ ." In child\n" ] ifTrueFalse ] invoke</lang>

UnixPipes

Demonstrating a subshell getting forked, and running concurrently with the original process

<lang bash>(echo "Process 1" >&2 ;sleep 5; echo "1 done" ) | (echo "Process 2";cat;echo "2 done")</lang>

X86 Assembly

Works with: NASM version Linux


While it IS possible to use native syscalls to create forks, it's not recommended. sys_fork requires manual setup for the pt_regs structure. It further requires you to enter kernal space using sysenter/exit pairs, setup the registers then call sys_fork. Linking to the C library is simply less work for user space forks. The only time it's really used is during debugging applications. <lang asm> extern fork extern printf

section .text global _start

_start: call fork cmp eax, 0 je _child jg _parent jmp _exit

_parent: push p_msg call printf jmp _exit _child: push c_msg call printf jmp _exit

_exit: push 0x1 mov eax, 1 push eax int 0x80 ret

section .data c_msg db "Printed from Child process",13,10,0 p_msg db "Printed from Parent process",13,10,0 </lang>