Fork: Difference between revisions
Line 167: | Line 167: | ||
[ "Hello form child" print flush 0 _exit ] [ drop "Hi from parent" print flush ] with-fork</lang> |
[ "Hello form child" print flush 0 _exit ] [ drop "Hi from parent" print flush ] with-fork</lang> |
||
=={{header|Fexl}}== |
=={{header|Fexl}}== |
||
There are many levels at which I can address this task. I'll start from the lowest possible level: |
|||
<lang fexl> |
|||
fork \pid |
|||
print "pid = ";print pid;nl; |
|||
</lang> |
|||
You'll see the output of two processes there, with the child process printing the 0: |
|||
<lang fexl> |
|||
pid = 10077 |
|||
pid = 0 |
|||
</lang> |
|||
<lang fexl> |
<lang fexl> |
Revision as of 17:26, 3 May 2012
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
<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
<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>
C
<lang c>#include <stdio.h>
- 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; }</lang>output<lang>waiting for child 3604...
child process: done
child 3604 finished</lang>
C++
<lang cpp>#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;
}</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.
<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>
Fexl
There are many levels at which I can address this task. I'll start from the lowest possible level: <lang fexl> fork \pid print "pid = ";print pid;nl; </lang>
You'll see the output of two processes there, with the child process printing the 0: <lang fexl> pid = 10077 pid = 0 </lang>
<lang fexl>
- 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; </lang>
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. <lang go>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) }
}</lang>
- Output:
PID: 28044 Child's PID: 28045 PID: 28045 Done.
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. <lang groovy>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"</lang>
Output:
BEFORE PROCESS BEFORE LOOP: 12:36:07 ..1 ..2 ..3 ..4 AFTER LOOP: 12:36:11 AFTER PROCESS
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>
Icon and Unicon
<lang Icon>procedure main()
if (fork()|runerr(500)) = 0 then write("child") else { delay(1000) write("parent") }
end</lang> 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.
Lua
<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>
Mathematica
This code will run a standalone Mathematica kernel, putting the result of a command in a temporary file: <lang Mathematica>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</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>
PARI/GP
This is a PARI implementation which uses fork()
via PARI's pari_daemon
. Of course fork()
could be used directly.
<lang C>void foo() {
if (pari_daemon()) pari_printf("Original\n"); else pari_printf("Fork\n");
}</lang>
Perl
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;
- parent code ...
run_fork {
child { # child code ... }
};
- 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
<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
<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
- 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) 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
- 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>
UNIX Shell
<lang bash>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</lang>
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.
<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>
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
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>
- 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
- PHP
- PicoLisp
- PL/I
- Pop11
- PureBasic/Omit
- Python
- Ruby
- Slate
- Smalltalk
- Standard ML
- Tcl
- Expect
- TclX
- Toka
- UNIX Shell
- UnixPipes
- X86 Assembly
- JavaScript/Omit
- TI-83 BASIC/Omit
- TI-89 BASIC/Omit
- Unlambda/Omit
- Retro/Omit
- ZX Spectrum Basic/Omit