Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Removing unreachable code #15281

Merged
merged 2 commits into from
Jun 1, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
69 changes: 5 additions & 64 deletions src/Compiler/Interactive/fsi.fs
Original file line number Diff line number Diff line change
Expand Up @@ -4463,8 +4463,6 @@ type FsiEvaluationSession
legacyReferenceResolver: LegacyReferenceResolver option
) =

do UnmanagedProcessExecutionOptions.EnableHeapTerminationOnCorruption() (* SDL recommendation *)

// Explanation: When FsiEvaluationSession.Create is called we do a bunch of processing. For fsi.exe
// and fsiAnyCpu.exe there are no other active threads at this point, so we can assume this is the
// unique compilation thread. For other users of FsiEvaluationSession it is reasonable to assume that
Expand Down Expand Up @@ -4625,9 +4623,9 @@ type FsiEvaluationSession
| Some assembly -> Some(Choice2Of2 assembly)
| None ->
#endif
match tcImports.TryFindExistingFullyQualifiedPathByExactAssemblyRef aref with
| Some resolvedPath -> Some(Choice1Of2 resolvedPath)
| None -> None
match tcImports.TryFindExistingFullyQualifiedPathByExactAssemblyRef aref with
| Some resolvedPath -> Some(Choice1Of2 resolvedPath)
| None -> None

let fsiDynamicCompiler =
FsiDynamicCompiler(
Expand Down Expand Up @@ -4739,68 +4737,11 @@ type FsiEvaluationSession
/// A host calls this to report an unhandled exception in a standard way, e.g. an exception on the GUI thread gets printed to stderr
member x.ReportUnhandledException exn = x.ReportUnhandledExceptionSafe true exn

member _.ReportUnhandledExceptionSafe isFromThreadException (exn: exn) =
member _.ReportUnhandledExceptionSafe _isFromThreadException (exn: exn) =
fsi.EventLoopInvoke(fun () ->
fprintfn fsiConsoleOutput.Error "%s" (exn.ToString())
diagnosticsLogger.SetError()

try
diagnosticsLogger.AbortOnError(fsiConsoleOutput)
with StopProcessing ->
// BUG 664864 some window that use System.Windows.Forms.DataVisualization types (possible FSCharts) was created in FSI.
// at some moment one chart has raised InvalidArgumentException from OnPaint, this exception was intercepted by the code in higher layer and
// passed to Application.OnThreadException. FSI has already attached its own ThreadException handler, inside it will log the original error
// and then raise StopProcessing exception to unwind the stack (and possibly shut down current Application) and get to DriveFsiEventLoop.
// DriveFsiEventLoop handles StopProcessing by suppressing it and restarting event loop from the beginning.
// This schema works almost always except when FSI is started as 64 bit process (FsiAnyCpu) on Windows 7.

// http://msdn.microsoft.com/en-us/library/windows/desktop/ms633573(v=vs.85).aspx
// Remarks:
// If your application runs on a 32-bit version of Windows operating system, uncaught exceptions from the callback
// will be passed onto higher-level exception handlers of your application when available.
// The system then calls the unhandled exception filter to handle the exception prior to terminating the process.
// If the PCA is enabled, it will offer to fix the problem the next time you run the application.
// However, if your application runs on a 64-bit version of Windows operating system or WOW64,
// you should be aware that a 64-bit operating system handles uncaught exceptions differently based on its 64-bit processor architecture,
// exception architecture, and calling convention.
// The following table summarizes all possible ways that a 64-bit Windows operating system or WOW64 handles uncaught exceptions.
// 1. The system suppresses any uncaught exceptions.
// 2. The system first terminates the process, and then the Program Compatibility Assistant (PCA) offers to fix it the next time
// you run the application. You can disable the PCA mitigation by adding a Compatibility section to the application manifest.
// 3. The system calls the exception filters but suppresses any uncaught exceptions when it leaves the callback scope,
// without invoking the associated handlers.
// Behavior type 2 only applies to the 64-bit version of the Windows 7 operating system.

// NOTE: tests on Win8 box showed that 64 bit version of the Windows 8 always apply type 2 behavior

// Effectively this means that when StopProcessing exception is raised from ThreadException callback - it won't be intercepted in DriveFsiEventLoop.
// Instead it will be interpreted as unhandled exception and crash the whole process.

// FIX: detect if current process in 64 bit running on Windows 7 or Windows 8 and if yes - swallow the StopProcessing and ScheduleRestart instead.
// Visible behavior should not be different, previously exception unwinds the stack and aborts currently running Application.
// After that it will be intercepted and suppressed in DriveFsiEventLoop.
// Now we explicitly shut down Application so after execution of callback will be completed the control flow
// will also go out of WinFormsEventLoop.Run and again get to DriveFsiEventLoop => restart the loop. I'd like the fix to be as conservative as possible
// so we use special case for problematic case instead of just always scheduling restart.

// http://msdn.microsoft.com/en-us/library/windows/desktop/ms724832(v=vs.85).aspx
let os = Environment.OSVersion
// Win7 6.1
let isWindows7 = os.Version.Major = 6 && os.Version.Minor = 1
// Win8 6.2
let isWindows8Plus = os.Version >= Version(6, 2, 0, 0)

if
isFromThreadException
&& ((isWindows7 && (IntPtr.Size = 8) && isWindows8Plus))
#if DEBUG
// for debug purposes
&& Environment.GetEnvironmentVariable("FSI_SCHEDULE_RESTART_WITH_ERRORS") = null
#endif
then
fsi.EventLoopScheduleRestart()
else
reraise ())
diagnosticsLogger.AbortOnError(fsiConsoleOutput))

member _.PartialAssemblySignatureUpdated =
fsiInteractionProcessor.PartialAssemblySignatureUpdated
Expand Down
44 changes: 0 additions & 44 deletions src/Compiler/Utilities/lib.fs
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,7 @@ open System
open System.Collections.Generic
open System.IO
open System.Text
open System.Threading
open System.Threading.Tasks
open System.Runtime.InteropServices
open Internal.Utilities.Collections
open Internal.Utilities.Library

Expand Down Expand Up @@ -381,48 +379,6 @@ type Dumper(x:obj) =
[<DebuggerBrowsable(DebuggerBrowsableState.Collapsed)>]
member self.Dump = sprintf "%A" x
#endif
//---------------------------------------------------------------------------
// EnableHeapTerminationOnCorruption()
//---------------------------------------------------------------------------

// USAGE: call UnmanagedProcessExecutionOptions.EnableHeapTerminationOnCorruption() from "main()".
// Note: This is not SDL required but recommended.
module UnmanagedProcessExecutionOptions =

[<DllImport("kernel32.dll")>]
extern UIntPtr private GetProcessHeap()

[<DllImport("kernel32.dll")>]
extern bool private HeapSetInformation(
UIntPtr _HeapHandle,
UInt32 _HeapInformationClass,
UIntPtr _HeapInformation,
UIntPtr _HeapInformationLength)

[<DllImport("kernel32.dll")>]
extern UInt32 private GetLastError()

// Translation of C# from http://swikb/v1/DisplayOnlineDoc.aspx?entryID=826 and copy in bug://5018
[<System.Security.Permissions.SecurityPermission(System.Security.Permissions.SecurityAction.Assert, UnmanagedCode = true)>]
let EnableHeapTerminationOnCorruption() =
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows) && Environment.OSVersion.Version.Major >= 6 && // If OS is Vista or higher
Environment.Version.Major < 3) then // and CLR not 3.0 or higher
// "The flag HeapSetInformation sets is available in Windows XP SP3 and later.
// The data structure used for heap information is available on earlier versions of Windows.
// The call will either return TRUE (found and set the flag) or false (flag not found).
// Not a problem in native code, so the program will merrily continue running.
// In managed code, the call to HeapSetInformation is a p/invoke.
// If HeapSetInformation returns FALSE then an exception will be thrown.
// If we are not running an OS which supports this (XP SP3, Vista, Server 2008, and Win7)
// then the call should not be made." -- see bug://5018.
// See also:
// http://blogs.msdn.com/michael_howard/archive/2008/02/18/faq-about-heapsetinformation-in-windows-vista-and-heap-based-buffer-overruns.aspx
let HeapEnableTerminationOnCorruption = 1u : uint32
if not (HeapSetInformation(GetProcessHeap(), HeapEnableTerminationOnCorruption, UIntPtr.Zero, UIntPtr.Zero)) then
raise (System.Security.SecurityException(
"Unable to enable unmanaged process execution option TerminationOnCorruption. " +
"HeapSetInformation() returned FALSE; LastError = 0x" +
GetLastError().ToString("X").PadLeft(8, '0') + "."))

[<RequireQualifiedAccess>]
type MaybeLazy<'T> =
Expand Down
3 changes: 0 additions & 3 deletions src/Compiler/Utilities/lib.fsi
Original file line number Diff line number Diff line change
Expand Up @@ -247,9 +247,6 @@ val inline cacheOptRef: cache: 'a option ref -> f: (unit -> 'a) -> 'a

val inline tryGetCacheValue: cache: cache<'a> -> NonNullSlot<'a> voption

module UnmanagedProcessExecutionOptions =
val EnableHeapTerminationOnCorruption: unit -> unit

[<RequireQualifiedAccess>]
type MaybeLazy<'T> =
| Strict of 'T
Expand Down
5 changes: 0 additions & 5 deletions src/fsc/fscmain.fs
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,10 @@ module internal FSharp.Compiler.CommandLineMain

open System
open System.Reflection
open System.Runtime
open System.Runtime.CompilerServices
open System.Threading

open Internal.Utilities.Library
open Internal.Utilities.Library.Extras
open FSharp.Compiler.AbstractIL
open FSharp.Compiler.AbstractIL.ILBinaryReader
open FSharp.Compiler.CompilerConfig
Expand Down Expand Up @@ -39,9 +37,6 @@ let main (argv) =
// Set the initial phase to garbage collector to batch mode, which improves overall performance.
use _ = UseBuildPhase BuildPhase.Parameter

// An SDL recommendation
UnmanagedProcessExecutionOptions.EnableHeapTerminationOnCorruption()

try

// We are on a compilation thread
Expand Down