Fork
You are encouraged to solve this task according to the task description, using any language you may know.
[edit] 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;
[edit] Aikido
var pid = fork()
switch (pid) {
case <0:
println ("fork error")
break
case 0:
println ("child")
break
default:
println ("parent")
break
}
[edit] ALGOL 68
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
)
Output:
This is new process This is the original process
[edit] AutoHotkey
MsgBox, 4, Fork, Start another process?
IfMsgBox, Yes
Run, %A_AhkPath% "%A_ScriptFullPath%"
MsgBox, 0, Fork, Stop this process.
[edit] C
#include <stdio.h>output
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
#include <err.h>
int main()
{
pid_t pid;
if (!(pid = fork())) {
usleep(10000);
printf("\tchild process: done\n");
} else if (pid < 0) {
err(1, "fork error");
} else {
printf("waiting for child %d...\n", (int)pid);
printf("child %d finished\n", (int)wait(0));
}
return 0;
}
waiting for child 3604...
child process: done
child 3604 finished
[edit] C++
#include<iostream>
#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;
}
[edit] 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.
(require '[clojure.java.shell :as shell])
(shell/sh "echo" "foo") ; evaluates to {:exit 0, :out "foo\n", :err ""}
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
(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))))
[edit] Common Lisp
There's not a standard way to fork, but some implementations have built-in bindings for POSIX fork.
(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."))))
[edit] 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").
Then you can compile your code and execute it:
c(fork).
fork:start().
[edit] Factor
This works only in the terminal, if used from the UI the child process won't print.
USING: unix unix.process ;
[ "Hello form child" print flush 0 _exit ] [ drop "Hi from parent" print flush ] with-fork
[edit] Fexl
There are many levels at which I can address this task. I'll start from the lowest possible level:
fork \pid
print "pid = ";print pid;nl;
- Output:
pid = 10077 pid = 0
The child process prints the 0, and the parent process prints the pid of that child, which in this case happened to be 10077.
At the next level up, we can define a "spawn" function which makes it easy to fork a child process and interact with its stdin, stdout, and stderr:
# (spawn child_fn next)
# Fork the child function as a process and return its pid, stdin, stdout, and
# stderr.
\spawn =
(
### Use error-checking versions of system routines
\pipe =
(\next
pipe \status\read\write
long_lt status 0 (die "pipe failed");
next read write
)
\dup2 =
(\oldfd\newfd\next
dup2 oldfd newfd \status
long_lt status 0 (die "dup2 failed");
next
)
\fdopen =
(\fd\mode\next
fdopen fd mode next;
die "fdopen failed"
)
\fork =
(\next
fork \pid
long_lt pid 0 (die "fork failed");
next pid
)
# Now here's the spawn function itself.
\child_fn\next
# First flush the parent's stdout and stderr to avoid any pending output
# accidentally getting pushed into the child's input. I've noticed this
# can happen when your script output is sent to a file or pipe instead of
# a console.
get_stdout \fh fflush fh \_
get_stderr \fh fflush fh \_
# Now create a series of pipes, each with a read and write side.
pipe \r_in\w_in
pipe \r_out\w_out
pipe \r_err\w_err
fork \pid
long_eq pid 0
(
# Child process.
# Duplicate one side of each pipe into stdin, stdout, and stderr
# as appropriate.
dup2 r_in 0;
dup2 w_out 1;
dup2 w_err 2;
# Close unused file handles. They're all unused because we duped the
# ones we need. Also, we must close w_in or the child hangs waiting
# for stdin to close.
close r_in; close w_in;
close r_out; close w_out;
close r_err; close w_err;
# Now run the child function, which can use stdin, stdout, and stderr
# normally.
child_fn
)
(
# Parent process. Open the opposite side of each pipe into three new
# file handles.
fdopen w_in "w" \child_in
fdopen r_out "r" \child_out
fdopen r_err "r" \child_err
# Close unused file handles. We don't close the ones we fdopened
# because they are still in play (i.e. fdopen does not dup).
close r_in;
close w_out;
close w_err;
# Return the child's pid, stdin, stdout, and stderr.
next pid child_in child_out child_err
)
)
Next, we define a test_pipe function to test the whole apparatus:
\test_pipe =
(\next
print "== test_pipe";nl;
### Handy
# Echo entire contents of stream fh to stdout.
\file_print ==
(\fh\next
fgetc fh \ch
long_lt ch 0 next;
putchar ch;
file_print fh next
)
# Show a stream with a descriptive label.
\show_stream =
(\label\fh\next
print "[ ";print label;print ":";nl;
file_print fh;
print "]";nl;
next
)
### Here is a child function to try with spawn.
\child_fn =
(\next
print "Hello from child.";nl;
get_stdin \stdin
show_stream "input from parent" stdin;
print "Good bye from child.";nl;
die "Oops the child had an error!";
next
)
# Spawn the child.
spawn child_fn \pid\child_in\child_out\child_err
# Now we can communicate with the child through its three file handles.
print "Hello from parent, child pid = ";print pid;print ".";nl;
# Say something to the child.
(
# Override print routines for convenience.
\print = (fwrite child_in)
\nl = (print NL)
# Start talking.
print "Hello child, I am your parent!";nl;
print "OK, nice talking with you.";nl;
);
print "The parent is now done talking to the child.";nl;
# Now show the child's stdout and stderr streams.
show_stream "output from child" child_out;
show_stream "error from child" child_err;
# Wait for child to finish.
wait \pid\status
# LATER shift and logical bit operators
# LATER WEXITSTATUS and other wait macros
\status = (long_div status 256)
print "Child ";print pid;print " exited with status ";
print status;print ".";nl;
print "Good bye from parent.";nl;
print "test_pipe completed successfully.";nl;
next
)
Finally we call the test function:
test_pipe;
- Output:
== test_pipe Hello from parent, child pid = 10391. The parent is now done talking to the child. [ output from child: Hello from child. [ input from parent: Hello child, I am your parent! OK, nice talking with you. ] Good bye from child. ] [ error from child: Oops the child had an error! ] Child 10391 exited with status 1. Good bye from parent. test_pipe completed successfully.
[edit] Go
This program prints its own pid, then runs a copy of itself if given any argument on the command line. When it does so, it prints the pid of the child process it started. Output should show this pid matching the child's self reported pid. See also package os/exec which offers a higher level interface and may be simpler in some situations. For the purpose of this task though, there is little difference.
package main
import (
"fmt"
"os"
)
func main() {
fmt.Printf("PID: %v\n", os.Getpid())
if len(os.Args) < 2 {
fmt.Println("Done.")
return
}
cp, err := os.StartProcess(os.Args[0], nil,
&os.ProcAttr{Files: []*os.File{nil, os.Stdout}},
)
if err != nil {
fmt.Println(err)
}
// Child process running independently at this point.
// We have its PID and can print it.
fmt.Printf("Child's PID: %v\n", cp.Pid)
if _, err = cp.Wait(); err != nil {
fmt.Println(err)
}
}
- Output:
PID: 28044 Child's PID: 28045 PID: 28045 Done.
[edit] Groovy
Like Java, Groovy controls the standard I/O streams of its child processes. Unlike Java, Groovy provides convenience methods on the Process class to make this burden somewhat easier to manage. This sample code launches the child process and then ties that process's regular and error output streams into the Groovy program's own such streams. This allows us to verify simply that the parent and child processes are running independently.
For the subprocess this example uses Cygwin's bash shell and commands running under MS Windows.
println "BEFORE PROCESS"
Process p = Runtime.runtime.exec('''
C:/cygwin/bin/sh -c "
/usr/bin/date +'BEFORE LOOP: %T';
for i in 1 2 3 4 ; do
/usr/bin/sleep 1;
/usr/bin/echo \$i;
done;
/usr/bin/date +'AFTER LOOP: %T'"
''')
p.consumeProcessOutput(System.out, System.err)
(0..<8).each {
Thread.sleep(500)
print '.'
}
p.waitFor()
println "AFTER PROCESS"
Output:
BEFORE PROCESS BEFORE LOOP: 12:36:07 ..1 ..2 ..3 ..4 AFTER LOOP: 12:36:11 AFTER PROCESS
[edit] Haskell
import System.Posix.Process
main = do
forkProcess (putStrLn "This is the new process")
putStrLn "This is the original process"
[edit] 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
[edit] Icon and Unicon
procedure main()
if (fork()|runerr(500)) = 0 then
write("child")
else {
delay(1000)
write("parent")
}
end
Notes:
- Fork should not fail. If an error 500 is generated there is a problem.
- Fork is not supported under windows. Multitasking should be used instead.
[edit] 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
[edit] Mathematica
This code will run a standalone Mathematica kernel, putting the result of a command in a temporary file:
commandstring = First[$CommandLine] <> " -noprompt -run \"Put[Factorial[20],ToFileName[$TemporaryDirectory,ToString[temp1]]];Quit[]\""
->"MathKernel -noprompt -run \"Put[Factorial[20],ToFileName[$TemporaryDirectory,ToString[temp1]]];Quit[]\""
Run[commandstring]
->0
[edit] 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";;
[edit] 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.
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"
[edit] PARI/GP
This is a PARI implementation which uses fork() via PARI's pari_daemon. Of course fork() could be used directly.
void
foo()
{
if (pari_daemon())
pari_printf("Original\n");
else
pari_printf("Fork\n");
}
[edit] Perl
In the child code, you may have to re-open database handles and such.
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);
}
Obviously you could do a Fork in a lot less lines, but this code covers all the bases.
Another example using Proc::Fork module:
use Proc::Fork;
run_fork {
child {
# child code ...
}
parent {
# parent code ...
}
};
Or:
use Proc::Fork;
# parent code ...
run_fork {
child {
# child code ...
}
};
# parent code continues ...
More complex example with retries and error handling:
use Proc::Fork;
run_fork {
child {
# child code ...
}
parent {
# parent code ...
}
retry {
# retry code ...
}
error {
# error handling ...
}
};
[edit] Perl 6
use NativeCall;
sub fork() returns Int is native { ... }
if fork() -> $pid {
print "I am the proud parent of $pid.\n";
}
else {
print "I am a child. Have you seen my mommy?\n";
}
- Output:
I am the proud parent of 17691. I am a child. Have you seen my mommy?
[edit] 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";
?>
[edit] PicoLisp
(unless (fork) # In child process
(println *Pid) # Print the child's PID
(bye) ) # and terminate
[edit] PL/I
ATTACH SOLVE (X) THREAD (T5);
[edit] Pop11
lvars ress;
if sys_fork(false) ->> ress then
;;; parent
printf(ress, 'Child pid = %p\n');
else
printf('In child\n');
endif;
[edit] Python
import os
pid = os.fork()
if pid > 0:
# parent code
else:
# child code
[edit] Racket
Looks like there are two popular things that people do for this task, so here are both. First, run some subprocess independently of Racket:
#lang racket
(define-values [P _out _in _err]
(subprocess (current-output-port) (current-input-port) (current-error-port)
(find-executable-path "du") "-hs" "/usr/share"))
;; wait for process to end, print messages as long as it runs
(let loop () (unless (sync/timeout 10 P) (printf "Still running...\n") (loop)))
Output:
Still running... Still running... Still running... ...snip... 15G /usr/share
Second, using fork() in its raw form, which is doable in racket, but as unsafe as you'd expect it to be:
#lang racket
(require ffi/unsafe)
(define fork (get-ffi-obj 'fork #f (_fun -> _int)))
(printf ">>> fork() => ~s\n" (fork))
Output:
>>> fork() => 23834 >>> fork() => 0
[edit] REXX
This function only works with Regina REXX.
child = fork()
[edit] Ruby
pid = fork
if pid
# parent code
else
# child code
end
or
fork do
# child code
end
# parent code
[edit] Run BASIC
You can run a program until that program executes a wait statement. Once the program waits,you can use it's functions.
run "someProgram.bas",#handle
render #handle ' this runs the program until it waits
' both the parent and child are running
' --------------------------------------------------------
' You can also call a function in the someProgram.bas program.
' For example if it had a DisplayBanner Funciton.
#handle DisplayBanner("Welcome!")
[edit] 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).
p@(Process traits) forkAndDo: b
[| ret |
(ret := lobby cloneSystem)
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]]
].
[edit] 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.
[edit] Standard ML
case Posix.Process.fork () of
SOME pid => print "This is the original process\n"
| NONE => print "This is the new process\n";
[edit] 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:
package require Expect
# 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."
}
}
}
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.
[edit] Toka
needs shell
getpid is-data PID
[ fork getpid PID = [ ." Child PID: " . cr ] [ ." In child\n" ] ifTrueFalse ] invoke
[edit] UNIX Shell
i=0
(while test $i -lt 10; do
sleep 1
echo "Child process"
i=`expr $i + 1`
done) &
while test $i -lt 5; do
sleep 2
echo "Parent process"
i=`expr $i + 1`
done
This uses the operator & to run the child process and the parent process at the same time. The output for the next 10 seconds is "Child process" every 1 second, and "Parent process" every 2 seconds. Both processes inherit i=0, but each process has its own i variable because processes are independent.
The original version of this code used a bash for-loop.
(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
[edit] UnixPipes
Demonstrating a subshell getting forked, and running concurrently with the original process
(echo "Process 1" >&2 ;sleep 5; echo "1 done" ) | (echo "Process 2";cat;echo "2 done")
[edit] X86 Assembly
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.
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
- Programming Tasks
- Programming environment operations
- Ada
- POSIX
- Aikido
- ALGOL 68
- AutoHotkey
- C
- C++
- Clojure
- Common Lisp
- Erlang
- Factor
- Fexl
- Go
- Groovy
- Haskell
- HicEst
- Icon
- Unicon
- Lua
- Mathematica
- OCaml
- Oz
- PARI/GP
- Perl
- Perl 6
- PHP
- PicoLisp
- PL/I
- Pop11
- PureBasic/Omit
- Python
- Racket
- REXX
- Ruby
- Run BASIC
- Slate
- Smalltalk
- Standard ML
- Tcl
- Expect
- TclX
- Toka
- UNIX Shell
- UnixPipes
- X86 Assembly
- JavaScript/Omit
- Maxima/Omit
- TI-83 BASIC/Omit
- TI-89 BASIC/Omit
- Unlambda/Omit
- Retro/Omit
- ZX Spectrum Basic/Omit