loader: build_module_importation invalidates the mmodule on errors
[nit.git] / lib / signals.nit
index 7d67bc0..f9709da 100644 (file)
 # limitations under the License.
 
 # Module to manage standard C signals
+#
+# 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
 
 `{
@@ -24,6 +66,21 @@ module signals
        #include <stdio.h>
 
        /*
+               This guard prevents errors by the C compiler when the Nit code imports this
+               module but do not use handle_signal. When it is _not_ used, the C type
+               SignalHandler and C function SignalHandler_receive_signal are not generated.
+               Which does not please the C compiler. This guard ensure that we compile this
+               code only if the type SignalHandler has been defined.
+
+               This is a HACK, FIXME by:
+               * Adding the macro to the FFI spec, or
+               * Attach the callbacks to this code block (or the module itself)
+               * Avoid using Nit types and callbacks or use them only in the C implementation
+                 of Nit method.
+       */
+       #ifdef NIT_TYPE_SignalHandler
+
+       /*
                Structure to manage each possible signals
                are used in an array of 32 maximum signals.
                This array is global to the software.
@@ -49,22 +106,53 @@ module signals
                        }
                }
        }
+
+       #endif
 `}
 
 # Receives the callback from system when a given signal arise
 interface SignalHandler
-       # Called on any signal received
-       fun receive_signal(signal: Int) `{
-       `}
-
-       # Called on any unsafe signal received
-       fun receive_signal_unsafe(signal: Int) `{
-       `}
+       # Invoked after a call to `check_signals` if a signal has been raised
+       # (should be redefed by subclasses)
+       #
+       # Should be used by most signals except `sigkill` and `sigstop` since they
+       # cannot be caught, blocked or ignored.
+       #
+       #     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) do end
+
+       # Called immediatly on receiving an unsafe signal (should be redefed by subclasses)
+       #
+       # Should be used for `sigkill` and `sigstop` since they cannot be caught,
+       # blocked or ignored.
+       #
+       # You should consider this methods as being fragile. It should be implemented in C
+       # and you should not do too much callbacks to Nit.
+       #
+       #     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) 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
+       #
+       # 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;