Program termination: Difference between revisions
added php |
No edit summary |
||
Line 8: | Line 8: | ||
However, this Rosetta Code task requires a simple stoppage of the program including all tasks. The simple way to achieve this is to abort the environment task. |
However, this Rosetta Code task requires a simple stoppage of the program including all tasks. The simple way to achieve this is to abort the environment task. |
||
<ada> |
<lang ada> |
||
with Ada.Task_Identification; use Ada.Task_Identification; |
with Ada.Task_Identification; use Ada.Task_Identification; |
||
Line 19: | Line 19: | ||
end if; |
end if; |
||
end Main; |
end Main; |
||
</ |
</lang> |
||
Aborting a task with Abort_Task is equivalent to ''abort'' statement, which is not used here because the environment task object is anonymous. The semantics of ''abort'' is as follows: |
Aborting a task with Abort_Task is equivalent to ''abort'' statement, which is not used here because the environment task object is anonymous. The semantics of ''abort'' is as follows: |
||
Line 35: | Line 35: | ||
With the first approach: |
With the first approach: |
||
<ada> |
<lang ada> |
||
procedure Main is |
procedure Main is |
||
-- Create as many task objects as your program needs |
-- Create as many task objects as your program needs |
||
Line 47: | Line 47: | ||
end if; |
end if; |
||
end Main; |
end Main; |
||
</ |
</lang> |
||
A task might look like: |
A task might look like: |
||
<ada> |
<lang ada> |
||
task body Some_Task is |
task body Some_Task is |
||
begin |
begin |
||
Line 64: | Line 64: | ||
end loop; |
end loop; |
||
end Some_Task; |
end Some_Task; |
||
</ |
</lang> |
||
With the second approach one simply returns from Main and all tasks are terminated by selecting the terminate alternative. Such tasks might look like: |
With the second approach one simply returns from Main and all tasks are terminated by selecting the terminate alternative. Such tasks might look like: |
||
<ada> |
<lang ada> |
||
task body Some_Task is |
task body Some_Task is |
||
begin |
begin |
||
Line 77: | Line 77: | ||
end loop; |
end loop; |
||
end Some_Task; |
end Some_Task; |
||
</ |
</lang> |
||
=={{header|ALGOL 68}}== |
=={{header|ALGOL 68}}== |
||
Line 88: | Line 88: | ||
=={{header|BASIC}}== |
=={{header|BASIC}}== |
||
{{works with|QuickBasic|4.5}} |
{{works with|QuickBasic|4.5}} |
||
<qbasic>if problem = 1 then |
<lang qbasic>if problem = 1 then |
||
end |
end |
||
end if</ |
end if</lang> |
||
=={{header|C}}== |
=={{header|C}}== |
||
<c>#include <stdlib.h> |
<lang c>#include <stdlib.h> |
||
if(problem){ |
if(problem){ |
||
Line 100: | Line 100: | ||
while anything else is an actual problem*/ |
while anything else is an actual problem*/ |
||
/*optionally: return the integerErrorCode from the main() function*/ |
/*optionally: return the integerErrorCode from the main() function*/ |
||
}</ |
}</lang> |
||
=={{header|C++}}== |
=={{header|C++}}== |
||
There are several ways to terminate a program. The following is mostly the same as in C: |
There are several ways to terminate a program. The following is mostly the same as in C: |
||
<cpp> |
<lang cpp> |
||
#include <cstdlib> |
#include <cstdlib> |
||
Line 111: | Line 111: | ||
std::exit(EXIT_FAILURE); |
std::exit(EXIT_FAILURE); |
||
} |
} |
||
</ |
</lang> |
||
The argument is the return value passed to the operating system. Returning 0 or the EXIT_SUCCESS signals successful termination to the calling process, EXIT_FAILURE signals failure. The meaning of any other value is implementation defined. |
The argument is the return value passed to the operating system. Returning 0 or the EXIT_SUCCESS signals successful termination to the calling process, EXIT_FAILURE signals failure. The meaning of any other value is implementation defined. |
||
On calling < |
On calling <tt>std::exit</tt>, all functions registered with std::atexit are called, and the destructors of all objects at namespace scope, as well as of all static objects already constructed, are called. However the destructors of automatic objects (i.e. local variables) are ''not'' called (and of course, objects allocated with new will not be destructed as well, except if one of the called destructors destroys them). Due to this inconsistency calling <tt>std::exit</tt> is often not a good idea. |
||
<cpp> |
<lang cpp> |
||
#include <cstdlib> |
#include <cstdlib> |
||
Line 123: | Line 123: | ||
std::abort(); |
std::abort(); |
||
} |
} |
||
</ |
</lang> |
||
Unlike < |
Unlike <tt>std::exit</tt>, <tt>std::abort</tt> will not do any cleanup other than the normal OS one. Also, it may cause other actions like producing a core dump or starting a debugger. |
||
<cpp> |
<lang cpp> |
||
#include <exception> |
#include <exception> |
||
Line 133: | Line 133: | ||
std::terminate(); |
std::terminate(); |
||
} |
} |
||
</ |
</lang> |
||
The function < |
The function <tt>std::terminate</tt> is what is automatically called when certain exception related failures happen. However it also can be called directly. By default it just calls abort, but unlike abort, its behaviour can be overridden with <tt>std::set_terminate</tt> (but it still must terminate the program in one way or anouther). Thererfore the amount of cleanup it does depends on whether it was overridden, and what the overridden function does. |
||
Note that returning a value from main is mostly equivalent to calling < |
Note that returning a value from main is mostly equivalent to calling <tt>std::exit</tt> with the returned value, except that automatic variables are correctly destructed. If one wants to return from an inner function, while still doing complete cleanup, a solution is to throw an exception caught in main (this will call the destructors of non-main local variables during stack unwinding), and to then return normally from main (which will destruct all automatic objects in main, and then do the cleanup like <tt>std::exit</tt>. |
||
=={{header|E}}== |
=={{header|E}}== |
||
Line 186: | Line 186: | ||
=={{header|Java}}== |
=={{header|Java}}== |
||
The call <tt>System.exit</tt> does not finalize any objects by default. This default is to keep the program thread-safe. From the javadocs for the method to change this default: "may result in finalizers being called on live objects while other threads are concurrently manipulating those objects, resulting in erratic behavior or deadlock." |
The call <tt>System.exit</tt> does not finalize any objects by default. This default is to keep the program thread-safe. From the javadocs for the method to change this default: "may result in finalizers being called on live objects while other threads are concurrently manipulating those objects, resulting in erratic behavior or deadlock." |
||
<java>if(problem){ |
<lang java>if(problem){ |
||
System.exit(integerErrorCode); |
System.exit(integerErrorCode); |
||
//conventionally, error code 0 is the code for "OK", |
//conventionally, error code 0 is the code for "OK", |
||
// while anything else is an actual problem |
// while anything else is an actual problem |
||
//optionally: Runtime.getRuntime().exit(integerErrorCode); |
//optionally: Runtime.getRuntime().exit(integerErrorCode); |
||
}</ |
}</lang> |
||
=={{header|Logo}}== |
=={{header|Logo}}== |
||
Line 204: | Line 204: | ||
=={{header|OCaml}}== |
=={{header|OCaml}}== |
||
{{example-needs-review|OCaml}} |
{{example-needs-review|OCaml}} |
||
<ocaml>if problem then |
<lang ocaml>if problem then |
||
exit integerErrorCode; |
exit integerErrorCode; |
||
(* conventionally, error code 0 is the code for "OK", |
(* conventionally, error code 0 is the code for "OK", |
||
while anything else is an actual problem *)</ |
while anything else is an actual problem *)</lang> |
||
=={{header|Perl}}== |
=={{header|Perl}}== |
||
{{example-needs-review|Perl}} |
{{example-needs-review|Perl}} |
||
<perl>if ($problem) { |
<lang perl>if ($problem) { |
||
exit integerErrorCode; |
exit integerErrorCode; |
||
# conventionally, error code 0 is the code for "OK" |
# conventionally, error code 0 is the code for "OK" |
||
# (you can also omit the argument in this case) |
# (you can also omit the argument in this case) |
||
# while anything else is an actual problem |
# while anything else is an actual problem |
||
}</ |
}</lang> |
||
=={{header|PHP}}== |
=={{header|PHP}}== |
||
<php>if (problem) |
<lang php>if (problem) |
||
exit(1);</ |
exit(1);</lang> |
||
=={{header|Pop11}}== |
=={{header|Pop11}}== |
||
Line 234: | Line 234: | ||
=={{header|Python}}== |
=={{header|Python}}== |
||
<python>if problem: |
<lang python>if problem: |
||
sys.exit(1)</ |
sys.exit(1)</lang> |
||
=={{header|Ruby}}== |
=={{header|Ruby}}== |
||
<ruby>if problem |
<lang ruby>if problem |
||
exit(1) |
exit(1) |
||
end</ |
end</lang> |
Revision as of 15:46, 3 February 2009
![Task](http://static.miraheze.org/rosettacodewiki/thumb/b/ba/Rcode-button-task-crushed.png/64px-Rcode-button-task-crushed.png)
You are encouraged to solve this task according to the task description, using any language you may know.
Show the syntax for a complete stoppage of a program inside a conditional. This includes all threads/processes which are part of your program.
Explain the cleanup (or lack thereof) caused by the termination (allocated memory, database connections, open files, object finalizers/destructors, run-on-exit hooks, etc.). Unless otherwise described, no special cleanup outside that provided by the operating system is provided.
Ada
Ada programs execute in one or more tasks. All tasks created during the execution of a program depend in a hierarchical manner on the task that create them, except for the environment task which executes the "main" procedure for the program. Each task will abort (terminate abnormally) if the task upon which it depends is aborted. This approach to task termination is not recommended because it does not allow tasks to terminate in a known state.
However, this Rosetta Code task requires a simple stoppage of the program including all tasks. The simple way to achieve this is to abort the environment task.
<lang ada> with Ada.Task_Identification; use Ada.Task_Identification;
procedure Main is
-- Create as many task objects as your program needs
begin
-- whatever logic is required in your Main procedure if some_condition then Abort_Task (Current_Task); end if;
end Main; </lang> Aborting a task with Abort_Task is equivalent to abort statement, which is not used here because the environment task object is anonymous. The semantics of abort is as follows:
- Abort is deferred until certain unbreakable actions are accomplished. These are protected actions on shared objects, initialization, assignment, and finalization of controlled objects, waiting for dependent tasks to be aborted;
- Local objects of the task are finalized;
- The tasks dependent on the aborted task are aborted.
- The state of external files will depend on the OS
The above is a preemptive way to abort tasks, which is not recommended to use, unless you firmly know what you are doing. A standard approach to such termination is either (or a combination of):
- to provide an entry in each task created by the environment task which, when called by the task upon which it depends, causes the called task to terminate in a known state;
- to provide "terminate" alternative open in each of such tasks.
In both cases the task objects are made local or otherwise destroyed upon completion of the main task. Note that destruction of a task always waits for its termination. If the task refuses to terminate it deadlocks.
With the first approach: <lang ada> procedure Main is
-- Create as many task objects as your program needs
begin
-- whatever logic is required in your Main procedure if some_condition then -- for each task created by the Main procedure The_task.Stop; -- end the Main procedure return; -- actually, this is not needed end if;
end Main; </lang> A task might look like: <lang ada> task body Some_Task is begin
loop select -- Some alternatives ... or accept Stop do -- Some cleanup while holding the caller is here end Stop; -- A cleanup asynchronous to the caller is here exit; -- We are through end select end loop;
end Some_Task; </lang> With the second approach one simply returns from Main and all tasks are terminated by selecting the terminate alternative. Such tasks might look like: <lang ada> task body Some_Task is begin
loop select -- Some alternatives ... or terminate; -- We are through end select end loop;
end Some_Task; </lang>
ALGOL 68
The label "stop" appears at the start of the standard-postlude and can be invoked to terminate any program.
IF problem = 1 THEN stop FI
The standard-postlude closes any opens files and basically wraps up execution.
BASIC
<lang qbasic>if problem = 1 then
end
end if</lang>
C
<lang c>#include <stdlib.h>
if(problem){
exit(integerErrorCode); /* conventionally, error code 0 is the code for "OK", while anything else is an actual problem*/ /*optionally: return the integerErrorCode from the main() function*/
}</lang>
C++
There are several ways to terminate a program. The following is mostly the same as in C: <lang cpp>
- include <cstdlib>
void problem_occured() {
std::exit(EXIT_FAILURE);
} </lang> The argument is the return value passed to the operating system. Returning 0 or the EXIT_SUCCESS signals successful termination to the calling process, EXIT_FAILURE signals failure. The meaning of any other value is implementation defined.
On calling std::exit, all functions registered with std::atexit are called, and the destructors of all objects at namespace scope, as well as of all static objects already constructed, are called. However the destructors of automatic objects (i.e. local variables) are not called (and of course, objects allocated with new will not be destructed as well, except if one of the called destructors destroys them). Due to this inconsistency calling std::exit is often not a good idea.
<lang cpp>
- include <cstdlib>
void problem_occured() {
std::abort();
} </lang> Unlike std::exit, std::abort will not do any cleanup other than the normal OS one. Also, it may cause other actions like producing a core dump or starting a debugger.
<lang cpp>
- include <exception>
void problem_occured() {
std::terminate();
} </lang> The function std::terminate is what is automatically called when certain exception related failures happen. However it also can be called directly. By default it just calls abort, but unlike abort, its behaviour can be overridden with std::set_terminate (but it still must terminate the program in one way or anouther). Thererfore the amount of cleanup it does depends on whether it was overridden, and what the overridden function does.
Note that returning a value from main is mostly equivalent to calling std::exit with the returned value, except that automatic variables are correctly destructed. If one wants to return from an inner function, while still doing complete cleanup, a solution is to throw an exception caught in main (this will call the destructors of non-main local variables during stack unwinding), and to then return normally from main (which will destruct all automatic objects in main, and then do the cleanup like std::exit.
E
Exit indicating successful completion:
if (true) { interp.exitAtTop() }
Exit indicating some problem:
if (true) { interp.exitAtTop("because the task said so") }
Forth
debug @ if QUIT \ quit back to the interpreter else BYE \ exit forth environment completely (e.g. end of a Forth shell script) then
Fortran
IF (condition) STOP [message] ! message is optional and is a character string. ! If present, the message is output to the standard output device.
Haskell
import Control.Monad import System.Exit when problem do exitWith ExitSuccess (* success *) exitWith (ExitFailure integerErrorCode) (* some failure with code *) exitFailure (* generic failure *)
J
Given condition, an integer which is zero if everything's OK (and we should NOT exit), or a non-zero exit code if there's a problem (and we should exit), then:
Tacit version:
2!:55^:] condition
Explicit version:
3 : 'if. 0~: condition do. 2!:55 condition end.'
Java
The call System.exit does not finalize any objects by default. This default is to keep the program thread-safe. From the javadocs for the method to change this default: "may result in finalizers being called on live objects while other threads are concurrently manipulating those objects, resulting in erratic behavior or deadlock." <lang java>if(problem){
System.exit(integerErrorCode); //conventionally, error code 0 is the code for "OK", // while anything else is an actual problem //optionally: Runtime.getRuntime().exit(integerErrorCode);
}</lang>
Logo
bye ; exits to shell
throw "toplevel ; exits to interactive prompt
pause ; escapes to interactive prompt for debugging continue ; resumes after a PAUSE
OCaml
<lang ocaml>if problem then
exit integerErrorCode; (* conventionally, error code 0 is the code for "OK", while anything else is an actual problem *)</lang>
Perl
<lang perl>if ($problem) {
exit integerErrorCode; # conventionally, error code 0 is the code for "OK" # (you can also omit the argument in this case) # while anything else is an actual problem
}</lang>
PHP
<lang php>if (problem)
exit(1);</lang>
Pop11
if condition then sysexit(); endif;
Python
<lang python>if problem:
sys.exit(1)</lang>
Ruby
<lang ruby>if problem
exit(1)
end</lang>
- Programming Tasks
- Basic language learning
- Ada
- ALGOL 68
- BASIC
- C
- C++
- E
- E examples needing attention
- Examples needing attention
- Forth
- Fortran
- Fortran examples needing attention
- Haskell
- Haskell examples needing attention
- J
- Java
- Logo
- OCaml
- OCaml examples needing attention
- Perl
- Perl examples needing attention
- PHP
- Pop11
- Pop11 examples needing attention
- Python
- Ruby