Program termination: Difference between revisions
→{{header|Go}}: added more techniques, removed note on error code values as this is not specified for Go.
({{header|UNIX Shell}}) |
(→{{header|Go}}: added more techniques, removed note on error code values as this is not specified for Go.) |
||
Line 258:
=={{header|Go}}==
Operating system resources such as memory and file handles are generally released on exit automatically, but this is not specified in the language definition. Proceses started with os.StartProcess or exec.Run are not automatically terminated by any of the techniques below and will continue to run after the main program terminates.
===Return statement===
Basically, a return statement executed from anywhere in main() terminates the program.
<lang go>func main() {
if problem {
return
}
}</lang>
Deferred functions are run when the enclosing function returns, so in the example below, function <tt>paperwork</tt> is run. This is the idiomatic mechanism for doing any kind of necessary cleanup.
Other goroutines are terminated unceremoniously when <tt>main</tt> returns. Below, <tt>main</tt> returns without waiting for <tt>pcj</tt> to complete.
The tantalizingly named <tt>SetFinalizer</tt> mechanism is also not invoked on program termination. It is designed for resource reclamation in long-running processes, not for program termination.
Returns from functions other than main do not cause program termination. In particular, return from a goroutine simply terminates that one goroutine, and not the entire program.
<lang go>package main
import (
"fmt"
"runtime"
"time"
)
const problem = true
func main() {
fmt.Println("main program start")
// this will get run on exit
defer paperwork()
// this will not run to completion
go pcj()
// this will not get run on exit
rec := &requiresExternalCleanup{"external object"}
runtime.SetFinalizer(rec, cleanup)
if problem {
fmt.Println("main program returning")
return
}
}
func paperwork() {
fmt.Println("i's dotted, t's crossed")
}
func pcj() {
fmt.Println("there's uncle Joe")
time.Sleep(1e10)
fmt.Println("movin kinda slow")
}
type requiresExternalCleanup struct {
id string
}
func cleanup(rec *requiresExternalCleanup) {
fmt.Println(rec.id, "cleanup")
}</lang>
Output:
<pre>
main program start
main program returning
there's uncle Joe
i's dotted, t's crossed
</pre>
===Os.Exit===
Os.Exit causes its argument to be returned to the operating system as a program exit code. Unlike the return statement, library function os.Exit exits promptly and does not run deferred functions.
<lang go>func main() {
fmt.Println("main program start")
// this will not get run on os.Exit
defer func() {
fmt.Println("deferred function")
}()
if problem {
fmt.Println("main program exiting")
os.Exit(-1)
}
}</lang>
Output:
<pre>
main program start
main program exiting
</pre>
===Panic===
Panics have some similarities to exceptions in other languages, including that there is a recovery mechanism allowing program termination to be averted. When the program terminates from panic however, it prints the panic value and then a stack trace for all goroutines.
Like the return statement, panic runs deferred functions. It run functions deferred from the current function, but then proceeds to unwind the call stack of the goroutine, calling deferred functions at each level. It does this only in the goroutine where panic was called. Deferred functions in other goroutines are not run and if panicking goes unrecovered and the program terminates, all other goroutines are terminated abruptly.
<lang go>func pcj() {
fmt.Println("at the junction")
defer func() {
fmt.Println("deferred from pcj")
}()
panic(10)
}
fmt.Println("main program start")
defer func() {
fmt.Println("deferred from main")
}()
go pcj()
time.Sleep(1e9)
fmt.Println("main program done")
}</lang>
Output:
<pre>
main program start
at the junction
deferred from pcj
panic: 10
(and the stack trace follows)
</pre>
=={{header|Haskell}}==
|