1(* 2 Title: Signal structure and signature. 3 Author: David Matthews 4 Copyright David Matthews 2000, 2008, 2019-20 5 6 This library is free software; you can redistribute it and/or 7 modify it under the terms of the GNU Lesser General Public 8 License as published by the Free Software Foundation; either 9 version 2.1 of the License, or (at your option) any later version. 10 11 This library is distributed in the hope that it will be useful, 12 but WITHOUT ANY WARRANTY; without even the implied warranty of 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 Lesser General Public License for more details. 15 16 You should have received a copy of the GNU Lesser General Public 17 License along with this library; if not, write to the Free Software 18 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 19*) 20 21(** 22Although the `Posix` structure in the Standard Basis Library provides functions 23which send signals to a process there is no standard method of handling signals. The 24`Signal` structure has been added to Poly/ML to allow signals to be blocked or 25handled. 26**) 27signature SIGNAL = 28sig 29 datatype sig_handle = SIG_DFL | SIG_IGN | SIG_HANDLE of int->unit 30 val signal: int * sig_handle -> sig_handle 31end; 32 33structure Signal: SIGNAL = 34struct 35 datatype sig_handle = SIG_DFL | SIG_IGN | SIG_HANDLE of int->unit 36 local 37 val setHandler = RunCall.rtsCallFull2 "PolySetSignalHandler" 38 in 39 fun signal(s, cmd) = 40 let 41 val c = 42 case cmd of 43 SIG_DFL => 0 44 | SIG_IGN => 1 45 | SIG_HANDLE f => RunCall.unsafeCast f 46 in 47 case setHandler(s, c) of 48 0 => SIG_DFL 49 | 1 => SIG_IGN 50 | f => SIG_HANDLE(RunCall.unsafeCast f) 51 end 52 end 53 54 local 55 datatype sigHandle = SigHandle of (int->unit) * int | WeakMarker 56 val waitForSig = RunCall.rtsCallFull0 "PolyWaitForSignal" 57 open Thread 58 59 fun sigThread(): unit = 60 let 61 (* This call to the RTS returns either a pair of a signal 62 and a handler or a flag indicating that some wek reference 63 has been set to NONE. These aren't logically related but 64 it's convenient to use a single thread for both. *) 65 val nextSig: sigHandle = waitForSig() 66 67 (* When we get a WeakMarker message we need to broadcast 68 on this condition variable. *) 69 fun broadCastWeak haveLock () = 70 ( 71 if haveLock then () else Mutex.lock Weak.weakLock; 72 ConditionVar.broadcast Weak.weakSignal; 73 Mutex.unlock Weak.weakLock 74 ) 75 76 in 77 case nextSig of 78 SigHandle (handler, signal) => (handler signal handle _ => ()) 79 | WeakMarker => 80 (* If the lock is free we can do the broadcast now but 81 to avoid waiting and being unable to handle any signals 82 we fork off a thread if we can't. *) 83 if Mutex.trylock Weak.weakLock 84 then broadCastWeak true () 85 else (Thread.fork(broadCastWeak false, []); ()); 86 sigThread() (* Forever. *) 87 end 88 89 fun forkThread() = 90 (Thread.fork(sigThread, []); ()) handle Thread _ => print "Unable to create signal thread\n" 91 92 in 93 (* Run this thread now and also start one each time we start up. *) 94 val _ = forkThread() 95 val _ = LibrarySupport.addOnEntry forkThread 96 end 97end; 98(** 99The `Signal.signal` function takes as its arguments a signal number and an 100action and returns the previous action. The action may be `SIG_DFL`, 101indicating the default action, `SIG_IGN`, indicating that the signal should be 102ignored (blocked) or `SIG_HANDLE`, which allows a handler function to be installed. 103 104Signals are represented as integers using the normal Unix signal numbering. In 105the Unix implementations of Poly/ML the type `Posix.Signal.signal` is the same as `int` 106so the constants from `Posix.Signal` can be used as arguments to `Signal.signal`. 107 108The default action depends on the signal. For some signals it is to ignore the 109signal, for others the process is killed. See the signal man page in Unix for a list 110of the default actions. 111 112A handler function installed using `SIG_HANDLE` is run as a separate thread 113some time after a signal arrives. 114 115Some signals are used internally by Poly/ML. In particular `SIGVTALRM` is used 116by the profiling mechanism. 117 118The Signal structure is provided in the Windows implementation but only the 119console interrupt signal (2) has effect. 120 121**) 122