diff --git a/src/Compiler/Interactive/fsi.fs b/src/Compiler/Interactive/fsi.fs index 5cd50aadff2..c7806622a65 100644 --- a/src/Compiler/Interactive/fsi.fs +++ b/src/Compiler/Interactive/fsi.fs @@ -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 @@ -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( @@ -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 diff --git a/src/Compiler/Utilities/lib.fs b/src/Compiler/Utilities/lib.fs index f4c37de4cf9..61cbd7e1c80 100755 --- a/src/Compiler/Utilities/lib.fs +++ b/src/Compiler/Utilities/lib.fs @@ -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 @@ -381,48 +379,6 @@ type Dumper(x:obj) = [] member self.Dump = sprintf "%A" x #endif -//--------------------------------------------------------------------------- -// EnableHeapTerminationOnCorruption() -//--------------------------------------------------------------------------- - -// USAGE: call UnmanagedProcessExecutionOptions.EnableHeapTerminationOnCorruption() from "main()". -// Note: This is not SDL required but recommended. -module UnmanagedProcessExecutionOptions = - - [] - extern UIntPtr private GetProcessHeap() - - [] - extern bool private HeapSetInformation( - UIntPtr _HeapHandle, - UInt32 _HeapInformationClass, - UIntPtr _HeapInformation, - UIntPtr _HeapInformationLength) - - [] - extern UInt32 private GetLastError() - - // Translation of C# from http://swikb/v1/DisplayOnlineDoc.aspx?entryID=826 and copy in bug://5018 - [] - 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') + ".")) [] type MaybeLazy<'T> = diff --git a/src/Compiler/Utilities/lib.fsi b/src/Compiler/Utilities/lib.fsi index 2e6b0318f7a..10ccfd21a21 100644 --- a/src/Compiler/Utilities/lib.fsi +++ b/src/Compiler/Utilities/lib.fsi @@ -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 - [] type MaybeLazy<'T> = | Strict of 'T diff --git a/src/fsc/fscmain.fs b/src/fsc/fscmain.fs index 1f1d7109304..3264e0ddf8a 100644 --- a/src/fsc/fscmain.fs +++ b/src/fsc/fscmain.fs @@ -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 @@ -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