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
 # 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
 
 `{
 module signals
 
 `{
@@ -24,6 +66,21 @@ module signals
        #include <stdio.h>
 
        /*
        #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.
                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
 `}
 
 # 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
 
        # 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;
        fun handle_signal(signal: Int, safely: Bool) import
                receive_signal `{
                SignalHandler last_handler;