Refine incomplete-pattern checks (Trac #4905)
[ghc-hetmet.git] / docs / users_guide / ffi-chap.xml
index b33e95a..47c0f01 100644 (file)
@@ -6,10 +6,10 @@
 Foreign function interface (FFI)
  </title>
 
-  <para>GHC (mostly) conforms to the Haskell 98 Foreign Function Interface
-  Addendum 1.0, whose definition is available from <ulink url="http://www.haskell.org/"><literal>http://www.haskell.org/</literal></ulink>.</para>
+  <para>GHC (mostly) conforms to the Haskell Foreign Function Interface,
+  whose definition is part of the Haskell Report on <ulink url="http://www.haskell.org/"><literal>http://www.haskell.org/</literal></ulink>.</para>
 
-  <para>To enable FFI support in GHC, give the <option>-XForeignFunctionInterface</option><indexterm><primary><option>-XForeignFunctionInterface</option></primary>
+  <para>FFI support is enabled by default, but can be enabled or disabled explicitly with the <option>-XForeignFunctionInterface</option><indexterm><primary><option>-XForeignFunctionInterface</option></primary>
     </indexterm> flag.</para>
 
   <para>GHC implements a number of GHC-specific extensions to the FFI
@@ -78,6 +78,86 @@ OK:
          details see the GHC developer wiki.
        </para>
       </sect2>
+
+      <sect2 id="ffi-interruptible">
+        <title>Interruptible foreign calls</title>
+        <para>
+          This concerns the interaction of foreign calls
+          with <literal>Control.Concurrent.throwTo</literal>.
+          Normally when the target of a <literal>throwTo</literal> is
+          involved in a foreign call, the exception is not raised
+          until the call returns, and in the meantime the caller is
+          blocked.  This can result in unresponsiveness, which is
+          particularly undesirable in the case of user interrupt
+          (e.g. Control-C).  The default behaviour when a Control-C
+          signal is received (<literal>SIGINT</literal> on Unix) is to raise
+          the <literal>UserInterrupt</literal> exception in the main
+          thread; if the main thread is blocked in a foreign call at
+          the time, then the program will not respond to the user
+          interrupt.
+        </para>
+        
+        <para>
+          The problem is that it is not possible in general to
+          interrupt a foreign call safely.  However, GHC does provide
+          a way to interrupt blocking system calls which works for
+          most system calls on both Unix and Windows.  A foreign call
+          can be annotated with <literal>interruptible</literal> instead
+          of <literal>safe</literal> or <literal>unsafe</literal>:
+
+<programlisting>
+foreign import ccall interruptible 
+   "sleep" :: CUint -> IO CUint
+</programlisting>
+
+          <literal>interruptble</literal> behaves exactly as
+          <literal>safe</literal>, except that when
+          a <literal>throwTo</literal> is directed at a thread in an
+          interruptible foreign call, an OS-specific mechanism will be
+          used to attempt to cause the foreign call to return:
+
+          <variablelist>
+            <varlistentry>
+              <term>Unix systems</term>
+              <listitem>
+                <para>
+                  The thread making the foreign call is sent
+                  a <literal>SIGPIPE</literal> signal
+                  using <literal>pthread_kill()</literal>.  This is
+                  usually enough to cause a blocking system call to
+                  return with <literal>EINTR</literal> (GHC by default
+                  installs an empty signal handler
+                  for <literal>SIGPIPE</literal>, to override the
+                  default behaviour which is to terminate the process
+                  immediately).
+                </para>
+              </listitem>
+            </varlistentry>
+            <varlistentry>
+              <term>Windows systems</term>
+              <listitem>
+                <para>
+                  [Vista and later only] The RTS calls the Win32
+                  function <literal>CancelSynchronousIO</literal>,
+                  which will cause a blocking I/O operation to return
+                  with the
+                  error <literal>ERROR_OPERATION_ABORTED</literal>.
+                </para>
+              </listitem>
+            </varlistentry>
+          </variablelist>
+
+          If the system call is successfully interrupted, it will
+          return to Haskell whereupon the exception can be raised.  Be
+          especially careful when
+          using <literal>interruptible</literal> that the caller of
+          the foreign function is prepared to deal with the
+          consequences of the call being interrupted; on Unix it is
+          good practice to check for <literal>EINTR</literal> always,
+          but on Windows it is not typically necessary to
+          handle <literal>ERROR_OPERATION_ABORTED</literal>.
+        </para>
+      </sect2>
   </sect1>
 
   <sect1 id="ffi-ghc">
@@ -484,7 +564,7 @@ int main(int argc, char *argv[])
           is platform dependent, but is intended to cause blocking
           system calls to return immediately with an interrupted error
           code.  The underlying operating system thread is not to be
-          destroyed.</para>
+          destroyed.  See <xref linkend="ffi-interruptible"/> for more details.</para>
       </sect3>
 
       <sect3 id="haskell-threads-and-os-threads">
@@ -566,7 +646,65 @@ int main(int argc, char *argv[])
           <literal>shutdownHaskellAndExit()</literal> instead).</para> 
       </sect3>
     </sect2>
-        
+
+    <sect2 id="ffi-floating-point">
+      <title>Floating point and the FFI</title>
+
+      <para>
+        The standard C99 <literal>fenv.h</literal> header
+        provides operations for inspecting and modifying the state of
+        the floating point unit.  In particular, the rounding mode
+        used by floating point operations can be changed, and the
+        exception flags can be tested.
+      </para>
+
+      <para>
+        In Haskell, floating-point operations have pure types, and the
+        evaluation order is unspecified.  So strictly speaking, since
+        the <literal>fenv.h</literal> functions let you change the
+        results of, or observe the effects of floating point
+        operations, use of <literal>fenv.h</literal> renders the
+        behaviour of floating-point operations anywhere in the program
+        undefined.
+      </para>
+
+      <para>
+        Having said that, we <emphasis>can</emphasis> document exactly
+        what GHC does with respect to the floating point state, so
+        that if you really need to use <literal>fenv.h</literal> then
+        you can do so with full knowledge of the pitfalls:
+        <itemizedlist>
+          <listitem>
+            <para>
+              GHC completely ignores the floating-point
+              environment, the runtime neither modifies nor reads it.
+            </para>
+          </listitem>
+          <listitem>
+            <para>
+              The floating-point environment is not saved over a
+              normal thread context-switch.  So if you modify the
+              floating-point state in one thread, those changes may be
+              visible in other threads.  Furthermore, testing the
+              exception state is not reliable, because a context
+              switch may change it.  If you need to modify or test the
+              floating point state and use threads, then you must use
+              bound threads
+              (<literal>Control.Concurrent.forkOS</literal>), because
+              a bound thread has its own OS thread, and OS threads do
+              save and restore the floating-point state.
+            </para>
+          </listitem>
+          <listitem>
+            <para>
+              It is safe to modify the floating-point unit state
+              temporarily during a foreign call, because foreign calls
+              are never pre-empted by GHC.
+            </para>
+          </listitem>
+        </itemizedlist>
+      </para>
+    </sect2>
   </sect1>
 </chapter>