...
This example creates a new file, outputs some text to it, and abruptly exits using Runtime.exit()
. Consequently, the file may be closed without the text actually being written.
Code Block | ||
---|---|---|
| ||
public class CreateFile {
public static void main(String[] args)
throws FileNotFoundException {
final PrintStream out =
new PrintStream(new BufferedOutputStream(
new FileOutputStream("foo.txt")));
out.println("hello");
Runtime.getRuntime().exit(1);
}
}
|
...
This solution explicitly closes the file before exiting.
Code Block | ||
---|---|---|
| ||
public class CreateFile {
public static void main(String[] args)
throws FileNotFoundException {
final PrintStream out =
new PrintStream(new BufferedOutputStream(
new FileOutputStream("foo.txt")));
try {
out.println("hello");
} finally {
try {
out.close();
} catch (IOException x) {
// handle error
}
}
Runtime.getRuntime().exit(1);
}
}
|
...
This compliant solution adds a shutdown hook to close the file. This hook is invoked by Runtime.exit()
and is called before the JVM is halted.
Code Block | ||
---|---|---|
| ||
public class CreateFile {
public static void main(String[] args)
throws FileNotFoundException {
final PrintStream out =
new PrintStream(new BufferedOutputStream(
new FileOutputStream("foo.txt")));
Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() {
public void run() {
out.close();
}
}));
out.println("hello");
Runtime.getRuntime().exit(1);
}
}
|
...
This noncompliant code example calls Runtime.halt()
instead of Runtime.exit()
. The Runtime.halt()
method stops the JVM without invoking any shutdown hooks; consequently the file is not properly written to or closed.
Code Block | ||
---|---|---|
| ||
public class CreateFile {
public static void main(String[] args)
throws FileNotFoundException {
final PrintStream out =
new PrintStream(new BufferedOutputStream(
new FileOutputStream("foo.txt")));
Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() {
public void run() {
out.close();
}
}));
out.println("hello");
Runtime.getRuntime().halt(1);
}
}
|
...
When a user forcefully exits a program, for example by pressing the ctrl + c
keys or by using the kill
command, the JVM terminates abruptly. Although this event cannot be captured, the program should nevertheless perform any mandatory cleanup operations before exiting. This noncompliant code example fails to do so.
Code Block | ||
---|---|---|
| ||
public class InterceptExit {
public static void main(String[] args)
throws FileNotFoundException {
InputStream in = null;
try {
in = new FileInputStream("file");
System.out.println("Regular code block");
// Abrupt exit such as ctrl + c key pressed
System.out.println("This never executes");
} finally {
if (in != null) {
try {
in.close(); // this never executes either
} catch (IOException x) {
// handle error
}
}
}
}
}
|
...
This compliant solution shows the standard method to install a hook.
Code Block | ||
---|---|---|
| ||
public class Hook {
public static void main(String[] args) {
try {
final InputStream in = new FileInputStream("file");
Runtime.getRuntime().addShutdownHook(new Thread() {
public void run() {
// Log shutdown and close all resources
in.close();
}
});
// ...
} catch (IOException x) {
// handle error
} catch (FileNotFoundException x) {
// handle error
}
}
}
|
...
Termination Strategy [REU] | |
CWE-705. Incorrect control flow scoping |
Android Implementation Details
Although most of the code examples are not applicable to the Android platform, the principle is applicable to Android. There are a number of ways to terminate a process on Android: android.app.Activity.finish()
, and the related finish...
methods, android.app.Activity.moveTaskToBack(boolean flag)
, android.os.Process.killProcess(int pid)
, System.exit()
.
Bibliography
[API 06] | |
Section 6.46, Termination Strategy [REU] |