X-Git-Url: http://nitlanguage.org diff --git a/lib/signals.nit b/lib/signals.nit index 91015da..440fd39 100644 --- a/lib/signals.nit +++ b/lib/signals.nit @@ -14,7 +14,49 @@ # See the License for the specific language governing permissions and # limitations under the License. -# Module to manage standard C signals +# ANSI C signal handling +# +# Common usage imply 5 steps: +# +# 1. Implement the `SignalHandler` interface +# 2. `redef receive_signal_unsafe` to handle `sigsegv` +# 3. `redef receive_signal` to handle other signals safely +# 4, Notify what signals to handle with `handle_signal` +# 5. If using the safe handler method, routinely call `check_signals` +# +# Usage example: +# +# ~~~~ +# class MyReceiver +# super SignalHandler +# +# redef fun receive_signal(signal) +# do +# print "received safely {signal}" +# if signal == sigalarm then print "Alarm!" +# end +# redef fun receive_signal_unsafe( signal ) do print "received unsafely {signal}" +# end +# +# var r = new MyReceiver +# +# # Handle `sigsegv` signal unsafely (the only way for this one) +# r.handle_signal(sigsegv, false) +# +# # Handle `sigint` and `sigalarm` safely +# r.handle_signal(sigint, true) +# r.handle_signal(sigalarm, true) +# +# # Ask system to receive a `sigalarm` signal in 1 second +# set_alarm(1) +# +# loop +# # Check signals and callback `receive_signal` +# var hit = check_signals +# +# if hit then break +# end +# ~~~~ module signals `{ @@ -22,6 +64,11 @@ module signals #define _POSIX_SOURCE 1 #include #include + #include + + /* + */ + void (*nit_SignalHandler_receive_signal)(void* self, long signal); /* Structure to manage each possible signals @@ -30,9 +77,9 @@ module signals */ struct nit_signals_ent { char raised; /* !=0 if has been raised */ - SignalHandler handler; /* instance to receive call */ + void* handler; /* instance to receive call */ char safely; /* if !=0 then manage signal safely, otherwise react when raised */ - } nit_signals_list[32] = {0x0}; + } nit_signals_list[32] = {{0}}; /* Receiver to all signals If unsafe, it calls directly the Nit receiver, @@ -45,7 +92,7 @@ module signals if (nit_signals_list[sig].safely) { nit_signals_list[sig].raised += 1; } else { - SignalHandler_receive_signal(nit_signals_list[sig].handler, sig); + nit_SignalHandler_receive_signal(nit_signals_list[sig].handler, sig); } } } @@ -61,16 +108,15 @@ interface SignalHandler # # class MyReceiver # super SignalHandler - # + # # redef fun receive_signal(signal) do print "received safely {signal}" # end - # + # # var r = new MyReceiver # r.handle_signal(sigint, true) # will call back when "check_signals" is called # # ... # check_signals # if a signal was received, it will invoke `r.receive_signal` - fun receive_signal(signal: Int) `{ - `} + fun receive_signal(signal: Int) do end # Called immediatly on receiving an unsafe signal (should be redefed by subclasses) # @@ -82,23 +128,20 @@ interface SignalHandler # # class MyReceiver # super SignalHandler - # + # # redef fun receive_signal_unsafe(signal) do print "received unsafely {signal}" # end - # + # # var r = new MyReceiver # r.handle_signal(sigsegv, false) # `r.receive_signal_unsafe` will be invoked on sigsegv - fun receive_signal_unsafe(signal: Int) `{ - `} + fun receive_signal_unsafe(signal: Int) do end # Set the receiver as the handler of the signal # # If `safely`, receiver will be called when `check_signals` in invoked # otherwise the receiver is invoked when the signal is raised, it may # crash the Nit system but is unavoidable for unstoppable signals. - fun handle_signal(signal: Int, safely: Bool) import - receive_signal `{ - SignalHandler last_handler; + fun handle_signal(signal: Int, safely: Bool) import receive_signal `{ if (signal < 32 && signal >=0) { struct sigaction act; sigemptyset(&act.sa_mask); @@ -107,20 +150,26 @@ interface SignalHandler sigaction(signal, &act, NULL); - last_handler = nit_signals_list[signal].handler; + #ifdef SignalHandler_decr_ref + SignalHandler last_handler = (SignalHandler)nit_signals_list[signal].handler; if (last_handler != NULL) SignalHandler_decr_ref(last_handler); + #endif + + nit_signals_list[signal].handler = self; - nit_signals_list[signal].handler = recv; - SignalHandler_incr_ref(recv); + #ifdef SignalHandler_incr_ref + SignalHandler_incr_ref(self); + #endif nit_signals_list[signal].safely = safely; + + nit_SignalHandler_receive_signal = SignalHandler_receive_signal; } `} # Set to ignore the signal fun ignore_signal(signal: Int) `{ - SignalHandler last_handler; if (signal < 32 && signal >=0) { struct sigaction act; sigemptyset(&act.sa_mask); @@ -128,15 +177,16 @@ interface SignalHandler act.sa_handler = SIG_IGN; sigaction(signal, &act, NULL); - last_handler = nit_signals_list[signal].handler; + #ifdef SignalHandler_decr_ref + SignalHandler last_handler = (SignalHandler)nit_signals_list[signal].handler; if (last_handler != NULL) SignalHandler_decr_ref(last_handler); + #endif } `} # Set default action for the signal fun default_signal(signal: Int) `{ - SignalHandler last_handler; if (signal < 32 && signal >=0) { struct sigaction act; sigemptyset(&act.sa_mask); @@ -144,9 +194,11 @@ interface SignalHandler act.sa_handler = SIG_DFL; sigaction(signal, &act, NULL); - last_handler = nit_signals_list[signal].handler; + #ifdef SignalHandler_decr_ref + SignalHandler last_handler = (SignalHandler)nit_signals_list[signal].handler; if (last_handler != NULL) SignalHandler_decr_ref(last_handler); + #endif } `} end @@ -164,7 +216,8 @@ redef interface Object if (nit_signals_list[sig].raised) { nit_signals_list[sig].raised = 0; raised_something = 1; - SignalHandler_receive_signal(nit_signals_list[sig].handler, sig); + SignalHandler handler = (SignalHandler)nit_signals_list[sig].handler; + SignalHandler_receive_signal(handler, sig); } return raised_something; @@ -181,88 +234,88 @@ redef class Process # Send the kill signal to the process fun kill do signal(sigkill) - + # Native implementation of `signal` private fun native_kill(pid, signal: Int) `{ kill(pid, signal); `} end # Hang up detected on controlling terminal or death of controlling process -protected fun sighup: Int do return 1 +fun sighup: Int do return 1 # Issued if the user sends an interrupt signal -protected fun sigint: Int do return 2 +fun sigint: Int do return 2 # Issued if the user sends a quit signal -protected fun sigquit: Int do return 3 +fun sigquit: Int do return 3 # Issued if the user attempts to execute an illegal, malformed, unknown, or privileged instruction -protected fun sigill: Int do return 4 +fun sigill: Int do return 4 # Issued when an exception occurs: a condition that a debugger has requested to be informed of -protected fun sigtrap: Int do return 5 +fun sigtrap: Int do return 5 # This signal is sent to a process to tell it to abort, i. e. to terminate -protected fun sigabrt: Int do return 6 +fun sigabrt: Int do return 6 # This signal is sent to a process when it causes a bus error -protected fun sigbus: Int do return 7 +fun sigbus: Int do return 7 # Issued if an illegal mathematical operation is attempted -protected fun sigfpe: Int do return 8 +fun sigfpe: Int do return 8 # If a process gets this signal it must quit immediately and will not perform any clean-up operations -protected fun sigkill: Int do return 9 +fun sigkill: Int do return 9 # Sent to a process to indicate user-defined conditions -protected fun sigusr1: Int do return 10 +fun sigusr1: Int do return 10 # Sent to a process when it makes an invalid virtual memory reference, or segmentation fault -protected fun sigsegv: Int do return 11 +fun sigsegv: Int do return 11 # Sent to a process to indicate user-defined conditions -protected fun sigusr2: Int do return 12 +fun sigusr2: Int do return 12 # Sent to a process when it attempts to write to a pipe without a process connected to the other end -protected fun sigpipe: Int do return 13 +fun sigpipe: Int do return 13 # Alarm Clock signal -protected fun sigalarm: Int do return 14 +fun sigalarm: Int do return 14 # Software termination signal -protected fun sigterm: Int do return 15 +fun sigterm: Int do return 15 # Sent to a process when a child process terminates or is interrupted -protected fun sigchild: Int do return 17 +fun sigchild: Int do return 17 # Tell the operating system to continue (restart) a process previously paused by the SIGSTOP or SIGTSTP signal -protected fun sigcont: Int do return 18 +fun sigcont: Int do return 18 # Tell the operating system to stop a process -protected fun sigstop: Int do return 19 +fun sigstop: Int do return 19 # Sent to a process by its terminal to request it to stop temporarily -protected fun sigtstp: Int do return 20 +fun sigtstp: Int do return 20 # Sent to a process when a socket has urgent or out-of-band data available to read -protected fun sigurg: Int do return 23 +fun sigurg: Int do return 23 # Sent to a process when it has used the CPU for a duration that exceeds a user-settable value -protected fun sigxcpu: Int do return 24 +fun sigxcpu: Int do return 24 # Sent to a process when it grows a file larger than the maximum allowed size -protected fun sigxfsz: Int do return 25 +fun sigxfsz: Int do return 25 # Virtual timer expired -protected fun sigvtalrm: Int do return 26 +fun sigvtalrm: Int do return 26 # Profiling timer expired -protected fun sigprof: Int do return 27 +fun sigprof: Int do return 27 -# Sent to a process when its controlling terminal changes its window size -protected fun sigwinch: Int do return 28 +# Sent to a process when its controlling terminal changes its window size +fun sigwinch: Int do return 28 # Sent to a process when the system experiences a power failure -protected fun sigpwr: Int do return 30 +fun sigpwr: Int do return 30 # Sent to a process when it passes a bad argument to a system call -protected fun sigsys: Int do return 31 +fun sigsys: Int do return 31