Fork: Difference between revisions
(→{{header|Clojure}}: add Clojure agent example) |
m (Fixed lang tags.) |
||
Line 5: | Line 5: | ||
{{works with|ALGOL 68G|Any - tested with release mk15-0.8b.fc9 - "fork" is not part of the standard's prelude.}} |
{{works with|ALGOL 68G|Any - tested with release mk15-0.8b.fc9 - "fork" is not part of the standard's prelude.}} |
||
<lang> |
<lang algol68>main: |
||
main: |
|||
( |
( |
||
INT pid; |
INT pid; |
||
Line 16: | Line 15: | ||
print("ERROR: Something went wrong") |
print("ERROR: Something went wrong") |
||
FI |
FI |
||
⚫ | |||
) |
|||
⚫ | |||
Output: |
Output: |
||
<pre> |
<pre> |
||
Line 55: | Line 53: | ||
{{libheader|POSIX}} |
{{libheader|POSIX}} |
||
<lang cpp> |
<lang cpp>#include<iostream> |
||
#include<iostream> |
|||
#include<unistd.h> |
#include<unistd.h> |
||
Line 77: | Line 74: | ||
return 0; |
return 0; |
||
⚫ | |||
} |
|||
⚫ | |||
=={{header|Clojure}}== |
=={{header|Clojure}}== |
||
Line 84: | Line 80: | ||
current state. To make sure the computation has finished, await can be used, or await-for for a bounded wait. |
current state. To make sure the computation has finished, await can be used, or await-for for a bounded wait. |
||
⚫ | |||
<lang clojure> |
|||
⚫ | |||
#'user/child |
#'user/child |
||
user=> (send child #(reduce + (take 1000 %))) |
user=> (send child #(reduce + (take 1000 %))) |
||
Line 92: | Line 87: | ||
nil |
nil |
||
user=> @child |
user=> @child |
||
500500 |
500500</lang> |
||
</lang> |
|||
=={{header|Common Lisp}}== |
=={{header|Common Lisp}}== |
||
Line 110: | Line 104: | ||
=={{header|Erlang}}== |
=={{header|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: |
Then you can compile your code and execute it: |
||
<lang erlang>c(fork). |
|||
fork:start().</lang> |
|||
=={{header|OCaml}}== |
=={{header|OCaml}}== |
||
Line 179: | Line 173: | ||
=={{header|Pop11}}== |
=={{header|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> |
|||
=={{header|Python}}== |
=={{header|Python}}== |
||
Line 214: | Line 208: | ||
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). |
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> |
<lang slate>p@(Process traits) forkAndDo: b |
||
p@(Process traits) forkAndDo: b |
|||
[ | ret | |
[ | ret | |
||
ret: (lobby cloneSystem). |
ret: (lobby cloneSystem). |
||
ret first ifTrue: [p pipes addLast: ret second. ret second] |
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]] |
ifFalse: [[p pipes clear. p pipes addLast: ret second. b applyWith: ret second] ensure: [lobby quit]] |
||
]. |
].</lang> |
||
</lang> |
|||
=={{header|Smalltalk}}== |
=={{header|Smalltalk}}== |
||
Line 240: | Line 232: | ||
<lang sml>case Posix.Process.fork () of |
<lang sml>case Posix.Process.fork () of |
||
SOME pid => print "This is the original process\n" |
SOME pid => print "This is the original process\n" |
||
| NONE => print "This is the new process\n"; |
| NONE => print "This is the new process\n";</lang> |
||
</lang> |
|||
=={{header|Tcl}}== |
=={{header|Tcl}}== |
||
Line 277: | Line 268: | ||
=={{header|Toka}}== |
=={{header|Toka}}== |
||
<lang toka>needs shell |
|||
getpid is-data PID |
|||
[ fork getpid PID = [ ." Child PID: " . cr ] [ ." In child\n" ] ifTrueFalse ] invoke</lang> |
|||
=={{header|UnixPipes}}== |
=={{header|UnixPipes}}== |
||
Demonstrating a subshell getting forked, and running concurrently with the original process |
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> |
|||
{{omit from|TI-83 BASIC}} {{omit from|TI-89 BASIC}} <!-- Does not have concurrency or background processes. --> |
{{omit from|TI-83 BASIC}} {{omit from|TI-89 BASIC}} <!-- Does not have concurrency or background processes. --> |
Revision as of 14:28, 20 November 2009
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.
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
Untested! <lang AutoHotkey>instancenum = %1%+1 MsgBox, 4, Fork Process, %instancenum% number: run another? IfMsgBox, Yes
Run, %A_ScriptFullName% %instancenum%
ExitApp</lang>
C
<lang c>#include <stdio.h>
- include <unistd.h>
int main() {
pid_t pid;
if( ( pid = fork() ) == 0) { printf("This is new process\n"); } else if (pid > 0) { printf("This is the original process\n"); } else { printf("ERROR: Something went wrong\n"); }
return 0;
}</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
In Clojure, a computation can be done asynchronously, with Clojure managing the thread pool, by creating an agent with an initial step. Computational requests are sent using 'send', and the agent can be dereferenced to obtain its current state. To make sure the computation has finished, await can be used, or await-for for a bounded wait.
<lang lisp>user=> (def child (agent (iterate inc 1)))
- 'user/child
user=> (send child #(reduce + (take 1000 %)))
- <Agent@215f7107: 500500>
user=> (await child) nil user=> @child 500500</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>
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>
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
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>
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). 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
package includes a fork. So does the
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>
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>