]> matita.cs.unibo.it Git - helm.git/blob - helm/hbugs/tutors/hbugs_deity.ml
- the mathql interpreter is not helm-dependent any more
[helm.git] / helm / hbugs / tutors / hbugs_deity.ml
1 (*
2  * Copyright (C) 2003:
3  *    Stefano Zacchiroli <zack@cs.unibo.it>
4  *    for the HELM Team http://helm.cs.unibo.it/
5  *
6  *  This file is part of HELM, an Hypertextual, Electronic
7  *  Library of Mathematics, developed at the Computer Science
8  *  Department, University of Bologna, Italy.
9  *
10  *  HELM is free software; you can redistribute it and/or
11  *  modify it under the terms of the GNU General Public License
12  *  as published by the Free Software Foundation; either version 2
13  *  of the License, or (at your option) any later version.
14  *
15  *  HELM is distributed in the hope that it will be useful,
16  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
17  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  *  GNU General Public License for more details.
19  *
20  *  You should have received a copy of the GNU General Public License
21  *  along with HELM; if not, write to the Free Software
22  *  Foundation, Inc., 59 Temple Place - Suite 330, Boston,
23  *  MA  02111-1307, USA.
24  *
25  *  For details, see the HELM World-Wide-Web page,
26  *  http://helm.cs.unibo.it/
27  *)
28
29 exception Can_t_kill of int * string ;; (* pid, reason *)
30
31  (* perform an action inside a critical section controlled by given mutex *)
32 let do_critical mutex =
33   fun action ->
34     try
35       Mutex.lock mutex;
36       let res = Lazy.force action in
37       Mutex.unlock mutex;
38       res 
39     with e -> Mutex.unlock mutex; raise e
40 ;;
41
42 let kill_signal = Sys.sigusr2 ;;    (* signal used to kill children *)
43 let chan = Event.new_channel () ;;  (* communication channel between threads *)
44
45   (* functions mangling "must die" PID list *)
46 let (add_to_dead_threads_walking, remove_from_dead_threads_walking, must_die) =
47   let dead_threads_walking = ref [] in
48   let mutex = Mutex.create () in
49   let add pid = do_critical mutex (lazy (
50       dead_threads_walking := pid :: !dead_threads_walking;
51   )) in
52   let remove pid = do_critical mutex (lazy (
53       dead_threads_walking := List.filter ((<>) pid) !dead_threads_walking
54   )) in
55   let is_in pid = do_critical mutex (lazy (
56       List.exists ((=) pid) !dead_threads_walking
57   )) in
58   (add, remove, is_in)
59 ;;
60
61   (* "kill_signal" handler, check if current process must die, if this is the
62   case exits with Thread.exit *)
63 ignore (Sys.signal kill_signal (Sys.Signal_handle
64   (fun signal ->
65     let myself = Unix.getpid () in
66     match signal with
67     | sg when (sg = kill_signal) && (must_die myself) ->
68         remove_from_dead_threads_walking myself;
69         prerr_endline "AYEEEEH!";
70         Thread.exit ()
71     | _ -> ())))
72 ;;
73
74   (* given a thread body (i.e. first argument of a Thread.create invocation)
75   return a new thread body which unblock the kill signal and send its pid to
76   parent over "chan" *)
77 let wrap_thread body =
78   fun arg ->
79     ignore (Unix.sigprocmask Unix.SIG_UNBLOCK [ kill_signal ]);
80     Event.sync (Event.send chan (Unix.getpid ()));
81     body arg
82 ;;
83
84 let creation_mutex = Mutex.create () ;;
85
86 let create body arg =
87   do_critical creation_mutex (lazy (
88       ignore (Thread.create (wrap_thread body) arg);
89       Event.sync (Event.receive chan)
90   ))
91 ;;
92 let kill pid =
93   add_to_dead_threads_walking pid;
94   try
95     Unix.kill pid kill_signal
96   with e -> raise (Can_t_kill (pid, Printexc.to_string e))
97 ;;
98
99   (* block kill signal in main process *)
100 ignore (Unix.sigprocmask Unix.SIG_BLOCK [ kill_signal ]) ;;
101