disallow shutdown from worker, which would lead to deadlock since the scheduler cannot terminate;
(*  Title:      Pure/Concurrent/time_limit.ML
    Author:     Makarius
Execution with time limit.
Notes:
  * There is considerable overhead due to fork of watchdog thread.
  * In rare situations asynchronous interrupts might be mistaken as
    timeout event, and turned into exception TimeOut accidentally.
*)
signature TIME_LIMIT =
sig
  exception TimeOut
  val timeLimit : Time.time -> ('a -> 'b) -> 'a -> 'b
end;
structure TimeLimit: TIME_LIMIT =
struct
exception TimeOut;
val wait_time = seconds 0.0001;
fun timeLimit time f x =
  Multithreading.with_attributes Multithreading.no_interrupts (fn orig_atts =>
    let
      val main = Thread.self ();
      val timeout = Unsynchronized.ref false;
      val watchdog = Simple_Thread.fork true (fn () =>
        (OS.Process.sleep time; timeout := true; Simple_Thread.interrupt_unsynchronized main));
      val result =
        Exn.capture (fn () => Multithreading.with_attributes orig_atts (fn _ => f x)) ();
      val _ = Simple_Thread.interrupt_unsynchronized watchdog;
      val _ = while Thread.isActive watchdog do OS.Process.sleep wait_time;
      val test = Exn.capture Multithreading.interrupted ();
    in
      if ! timeout andalso (Exn.is_interrupt_exn result orelse Exn.is_interrupt_exn test)
      then raise TimeOut
      else if Exn.is_interrupt_exn test then Exn.interrupt ()
      else Exn.release result
    end);
end;