Abrupt process termination via the End statement or Environment.Exit
ID |
vbnet.maintainability.no_exit_method_call |
Severity |
critical |
Remediation Complexity |
medium |
Remediation Risk |
medium |
Remediation Effort |
low |
Resource |
Control Flow |
Language |
VB.NET |
Description
Reports the Visual Basic End statement used on its own to stop the program, and calls to Environment.Exit(…), including the fully qualified System.Environment.Exit(…). Block terminators that merely happen to begin with the same keyword are not reported - End If, End Sub, End Select, End Class - nor is the #End Region directive, and neither is Application.Exit(), which requests a graceful shutdown rather than killing the process.
Rationale
Both forms stop the runtime where they stand. No Finally block runs, no Using scope closes, Dispose is never called, so buffered writes are dropped, open transactions are left for the server to time out and half-written files stay half-written - the abrupt exit turns a handled error path into data loss. The code also stops being usable anywhere but at the top of a console application: called from a class library it kills whatever host loaded it, so one bad input to a request handler takes down the worker process serving every other request, and a test that reaches the statement takes the test runner with it instead of failing. Finally, an exit code carries no diagnosis, so the reason for stopping - which the code knows at that moment - never reaches whoever has to explain the outage.
The following code illustrates the pattern detected by this rule:
Public Sub RunBatch(ByVal path As String)
If Not IO.File.Exists(path) Then
Console.WriteLine("input file missing")
' FLAGGED: Abrupt process termination via the End statement or Environment.Exit
End
End If
Process(path)
End Sub
Remediation
Report the problem to the caller and let it decide what to do: return a status value, or throw the exception that describes the situation, as in Throw New IO.FileNotFoundException("input file missing", path). Keep the decision to end the process in the entry point alone, where Sub Main can catch what reached it, log it and return an exit code or set Environment.ExitCode - that way cleanup along the whole call stack still runs. In a UI application, request a shutdown through the framework instead, for example Application.Exit(), so forms are given the chance to close and save.