anchor.diff:  
                   // FSI error logging on switched to thread
                   InstallErrorLoggingOnThisThread errorLogger
  -#if FX_LCIDFROMCODEPAGE
                   use _scope = SetCurrentUICultureForThread fsiOptions.FsiLCID
  -#endif
                   f ctok istate) 
           with _ -> 
               (istate,Completed None)
  
positive.code:     | ExitRequest 
      | PrintInterruptRequest
  
  type internal FsiInterruptController(fsiOptions : FsiCommandLineOptions, 
                                       fsiConsoleOutput: FsiConsoleOutput) = 
  
      let mutable stdinInterruptState = StdinNormal
      let CTRL_C = 0 
      let mutable interruptAllowed = InterruptIgnored
      let mutable killThreadRequest = NoRequest
      let mutable ctrlEventHandlers = [] : NativeMethods.ControlEventHandler list 
      let mutable ctrlEventActions  = [] : (unit -> unit) list 
      let mutable exitViaKillThread = false
  
      let mutable posixReinstate = (fun () -> ())
  
      member __.Exit() = 
          if exitViaKillThread then 
              killThreadRequest <- ExitRequest
              Thread.Sleep(1000)
          exit 0
  
      member __.FsiInterruptStdinState with get () = stdinInterruptState and set v = stdinInterruptState <- v
  
      member __.ClearInterruptRequest() = killThreadRequest <- NoRequest
      
      member __.InterruptAllowed with set v = interruptAllowed <- v
      
      member __.Interrupt() = ctrlEventActions |> List.iter (fun act -> act())
      
      member __.EventHandlers = ctrlEventHandlers
  
      // REVIEW: streamline all this code to use the same code on Windows and Posix.   
      member controller.InstallKillThread(threadToKill:Thread, pauseMilliseconds:int) = 
  #if DYNAMIC_CODE_EMITS_INTERRUPT_CHECKS
          let action() =
              Microsoft.FSharp.Silverlight.InterruptThread(threadToKill.ManagedThreadId)
  
          ctrlEventActions  <- action           :: ctrlEventActions;
  #else
  #if FX_NO_THREADABORT
          ignore threadToKill
          ignore pauseMilliseconds
          ignore fsiConsoleOutput
          ignore CTRL_C
          ignore fsiOptions
          exitViaKillThread <- false
  #else
          if !progress then fprintfn fsiConsoleOutput.Out "installing CtrlC handler"
          // WINDOWS TECHNIQUE: .NET has more safe points, and you can do more when a safe point. 
          // Hence we actually start up the killer thread within the handler. 
          try 
              let raiseCtrlC() = 
  #if FX_LCIDFROMCODEPAGE
                  use _scope = SetCurrentUICultureForThread fsiOptions.FsiLCID
  #else
                  ignore fsiOptions
  #endif
                  fprintf fsiConsoleOutput.Error "%s" (FSIstrings.SR.fsiInterrupt())
                  stdinInterruptState <- StdinEOFPermittedBecauseCtrlCRecentlyPressed
                  if (interruptAllowed = InterruptCanRaiseException) then 
                      killThreadRequest <- ThreadAbortRequest
                      let killerThread = 
                          new Thread(new ThreadStart(fun () ->
  #if FX_LCIDFROMCODEPAGE
                              use _scope = SetCurrentUICultureForThread fsiOptions.FsiLCID
  #endif
                              // sleep long enough to allow ControlEventHandler handler on main thread to return 
                              // Also sleep to give computations a bit of time to terminate 
                              Thread.Sleep(pauseMilliseconds)
                              if (killThreadRequest = ThreadAbortRequest) then 
                                  if !progress then fsiConsoleOutput.uprintnfn "%s" (FSIstrings.SR.fsiAbortingMainThread())  
                                  killThreadRequest <- NoRequest
                                  threadToKill.Abort()
                              ()),Name="ControlCAbortThread") 
                      killerThread.IsBackground <- true
                      killerThread.Start() 
          
              let ctrlEventHandler = new NativeMethods.ControlEventHandler(fun i ->  if i = CTRL_C then (raiseCtrlC(); true) else false ) 
              ctrlEventHandlers <- ctrlEventHandler :: ctrlEventHandlers
              ctrlEventActions  <- raiseCtrlC       :: ctrlEventActions
              let _resultOK = NativeMethods.SetConsoleCtrlHandler(ctrlEventHandler,true)
              exitViaKillThread <- false // don't exit via kill thread
          with e -> 
              if !progress then fprintfn fsiConsoleOutput.Error "Failed to install ctrl-c handler using Windows technique - trying to install one using Unix signal handling...";
              // UNIX TECHNIQUE: We start up a killer thread, and it watches the mutable reference location.    
              // We can't have a dependency on Mono DLLs (indeed we don't even have them!)
              // So SOFT BIND the following code:
              // Mono.Unix.Native.Stdlib.signal(Mono.Unix.Native.Signum.SIGINT,new Mono.Unix.Native.SignalHandler(fun n -> PosixSignalProcessor.PosixInvoke(n))) |> ignore;
              match (try Choice1Of2(Assembly.Load(new System.Reflection.AssemblyName("Mono.Posix, Version=2.0.0.0, Culture=neutral, PublicKeyToken=0738eb9f132ed756"))) with e -> Choice2Of2 e) with 
              | Choice1Of2(monoPosix) -> 
                try
                  if !progress then fprintfn fsiConsoleOutput.Error "loading type Mono.Unix.Native.Stdlib..."
                  let monoUnixStdlib = monoPosix.GetType("Mono.Unix.Native.Stdlib") 
                  if !progress then fprintfn fsiConsoleOutput.Error "loading type Mono.Unix.Native.SignalHandler..."
                  let monoUnixSignalHandler = monoPosix.GetType("Mono.Unix.Native.SignalHandler") 
                  if !progress then fprintfn fsiConsoleOutput.Error "creating delegate..."
                  controller.PosixInvoke(-1)
                  let monoHandler = System.Delegate.CreateDelegate(monoUnixSignalHandler,controller,"PosixInvoke") 
                  if !progress then fprintfn fsiConsoleOutput.Error "registering signal handler..."
                  let monoSignalNumber = System.Enum.Parse(monoPosix.GetType("Mono.Unix.Native.Signum"),"SIGINT")
                  let register () = Utilities.callStaticMethod monoUnixStdlib "signal" [ monoSignalNumber; box monoHandler ]  |> ignore 
                  posixReinstate <- register
                  register()
                  let killerThread = 
                      new Thread(new ThreadStart(fun () ->
  #if FX_LCIDFROMCODEPAGE
                          use _scope = SetCurrentUICultureForThread fsiOptions.FsiLCID
  #endif
                          while true do 
                              //fprintf fsiConsoleOutput.Error "\n- kill thread loop...\n"; errorWriter.Flush();  
                              Thread.Sleep(pauseMilliseconds*2)
                              match killThreadRequest with 
                              | PrintInterruptRequest -> 
                                  fprintf fsiConsoleOutput.Error "%s" (FSIstrings.SR.fsiInterrupt()); fsiConsoleOutput.Error.Flush()  
                                  killThreadRequest <- NoRequest
                              | ThreadAbortRequest -> 
                                  fprintf fsiConsoleOutput.Error  "%s" (FSIstrings.SR.fsiInterrupt()); fsiConsoleOutput.Error.Flush()  
                                  if !progress then fsiConsoleOutput.uprintnfn "%s" (FSIstrings.SR.fsiAbortingMainThread())
                                  killThreadRequest <- NoRequest
                                  threadToKill.Abort()
                              | ExitRequest -> 
                                  // Mono has some weird behaviour where it blocks on exit
                                  // once CtrlC has ever been pressed.  Who knows why?  Perhaps something
                                  // to do with having a signal handler installed, but it only happens _after_
                                  // at least one CtrLC has been pressed.  Maybe raising a ThreadAbort causes
                                  // exiting to have problems.
                                  //
                                  // Anyway, we make "#q" work this case by setting ExitRequest and brutally calling
                                  // the process-wide 'exit'
                                  fprintf fsiConsoleOutput.Error  "%s" (FSIstrings.SR.fsiExit()); fsiConsoleOutput.Error.Flush()  
                                  Utilities.callStaticMethod monoUnixStdlib "exit" [ box 0 ] |> ignore
                              | _ ->  ()
                          done),Name="ControlCAbortAlternativeThread") 
                  killerThread.IsBackground <- true
                  killerThread.Start()
                  // exit via kill thread to workaround block-on-exit bugs with Mono once a CtrlC has been pressed
                  exitViaKillThread <- true 
                with e -> 
                  fprintf fsiConsoleOutput.Error  "%s" (FSIstrings.SR.fsiCouldNotInstallCtrlCHandler(e.Message))
                  exitViaKillThread <- false
              | Choice2Of2 e ->
                fprintf fsiConsoleOutput.Error  "%s" (FSIstrings.SR.fsiCouldNotInstallCtrlCHandler(e.Message))
                exitViaKillThread <- false  
  #endif
  
  
      member x.PosixInvoke(n:int) = 
           // we run this code once with n = -1 to make sure it is JITted before execution begins
  
negative.code:     member __.EvalExpression (ctok, sourceText, scriptFileName, errorLogger) =
          use _unwind1 = ErrorLogger.PushThreadBuildPhaseUntilUnwind(ErrorLogger.BuildPhase.Interactive)
          use _unwind2 = ErrorLogger.PushErrorLoggerPhaseUntilUnwind(fun _ -> errorLogger)
          use _scope = SetCurrentUICultureForThread fsiOptions.FsiLCID
          let lexbuf = UnicodeLexing.StringAsLexbuf(sourceText)
          let tokenizer = fsiStdinLexerProvider.CreateBufferLexer(scriptFileName, lexbuf, errorLogger)
          currState 
  