Documentation updates for #1177
authorSimon Marlow <simonmar@microsoft.com>
Thu, 26 Jul 2007 09:40:30 +0000 (09:40 +0000)
committerSimon Marlow <simonmar@microsoft.com>
Thu, 26 Jul 2007 09:40:30 +0000 (09:40 +0000)
We now have a section that describes what hs_exit() does (including
the "wait for foreign calls to return" behaviour), and more
documentation on creating libraries of Haskell code.  I also imported
the section "Beware of DllMain()!" from the haskell.org wiki, with
some minor editing.

docs/users_guide/ffi-chap.xml
docs/users_guide/win32-dlls.xml

index 82f3899..96cbd59 100644 (file)
@@ -10,37 +10,25 @@ Foreign function interface (FFI)
   Addendum 1.0, whose definition is available from <ulink url="http://haskell.org/"><literal>http://haskell.org/</literal></ulink>.</para>
 
   <para>To enable FFI support in GHC, give the <option>-fffi</option><indexterm><primary><option>-fffi</option></primary>
-    </indexterm>flag, or
+    </indexterm> flag, or
 the <option>-fglasgow-exts</option><indexterm><primary><option>-fglasgow-exts</option></primary>
     </indexterm> flag which implies <option>-fffi</option>
 .</para>
 
-  <para>The FFI support in GHC diverges from the Addendum in the following ways:</para>
-
-  <itemizedlist>
-    <listitem>
-      <para>Syntactic forms and library functions proposed in earlier versions
-      of the FFI are still supported for backwards compatibility.</para>
-    </listitem>
-
-    <listitem>
-      <para>GHC implements a number of GHC-specific extensions to the FFI
-      Addendum.  These extensions are described in <xref linkend="ffi-ghcexts" />, but please note that programs using
-      these features are not portable.  Hence, these features should be
-      avoided where possible.</para>
-    </listitem>
-  </itemizedlist>
+  <para>GHC implements a number of GHC-specific extensions to the FFI
+    Addendum.  These extensions are described in <xref linkend="ffi-ghcexts" />, but please note that programs using
+    these features are not portable.  Hence, these features should be
+    avoided where possible.</para>
 
   <para>The FFI libraries are documented in the accompanying library
-  documentation; see for example the <literal>Foreign</literal>
-  module.</para>
+  documentation; see for example the
+    <ulink url="../libraries/base/Control-Concurrent.html"><literal>Foreign</literal></ulink> module.</para>
 
   <sect1 id="ffi-ghcexts">
     <title>GHC extensions to the FFI Addendum</title>
 
     <para>The FFI features that are described in this section are specific to
-    GHC.  Avoid them where possible to not compromise the portability of the
-    resulting code.</para>
+    GHC.  Your code will not be portable to other compilers if you use them.</para>
 
     <sect2>
       <title>Unboxed types</title>
@@ -78,7 +66,6 @@ OK:
 </programlisting>
 </para>
       </sect2>
-
   </sect1>
 
   <sect1 id="ffi-ghc">
@@ -137,6 +124,13 @@ extern HsInt foo(HsInt a0);</programlisting>
        <option>-stubdir</option> option; see <xref linkend="options-output"
          />.</para>
 
+      <para>When linking the program, remember to include
+        <filename>M_stub.o</filename> in the final link command line, or
+        you'll get link errors for the missing function(s) (this isn't
+        necessary when building your program with <literal>ghc
+        &ndash;&ndash;make</literal>, as GHC will automatically link in the
+        correct bits).</para>
+
       <sect3 id="using-own-main"> 
        <title>Using your own <literal>main()</literal></title>
 
@@ -188,10 +182,10 @@ int main(int argc, char *argv[])
        <para>The call to <literal>hs_init()</literal>
        initializes GHC's runtime system.  Do NOT try to invoke any
        Haskell functions before calling
-       <literal>hs_init()</literal>: strange things will
+       <literal>hs_init()</literal>: bad things will
        undoubtedly happen.</para>
 
-       <para>We pass <literal>argc</literal> and
+       <para>We pass references to <literal>argc</literal> and
        <literal>argv</literal> to <literal>hs_init()</literal>
        so that it can separate out any arguments for the RTS
        (i.e. those arguments between
@@ -251,10 +245,8 @@ int main(int argc, char *argv[])
       </informaltable>
 
        <para>After we've finished invoking our Haskell functions, we
-       can call <literal>hs_exit()</literal>, which
-       terminates the RTS.  It runs any outstanding finalizers and
-       generates any profiling or stats output that might have been
-       requested.</para>
+       can call <literal>hs_exit()</literal>, which terminates the
+       RTS.</para>
 
        <para>There can be multiple calls to
        <literal>hs_init()</literal>, but each one should be matched
@@ -273,23 +265,87 @@ int main(int argc, char *argv[])
        to the <literal>Main</literal> Haskell module.</para>
       </sect3>
 
-      <sect3 id="foreign-export-dynamic-ghc">
-       <title>Using <literal>foreign import ccall "wrapper"</literal> with GHC</title>
+      <sect3 id="ffi-library">
+        <title>Making a Haskell library that can be called from foreign
+          code</title>
 
-       <indexterm><primary><literal>foreign import
-       ccall "wrapper"</literal></primary><secondary>with GHC</secondary>
-       </indexterm>
+        <para>The scenario here is much like in <xref linkend="using-own-main"
+            />, except that the aim is not to link a complete program, but to
+          make a library from Haskell code that can be deployed in the same
+          way that you would deploy a library of C code.</para>
 
-       <para>When <literal>foreign import ccall "wrapper"</literal> is used
-        in a Haskell module, The C stub file <filename>M_stub.c</filename>
-        generated by GHC contains small helper functions used by the code
-        generated for the imported wrapper, so it must be linked in to the
-        final program.  When linking the program, remember to include
-        <filename>M_stub.o</filename> in the final link command line, or
-        you'll get link errors for the missing function(s) (this isn't
-        necessary when building your program with <literal>ghc
-        &ndash;&ndash;make</literal>, as GHC will automatically link in the
-        correct bits).</para>
+        <para>The main requirement here is that the runtime needs to be
+          initialized before any Haskell code can be called, so your library
+          should provide initialisation and deinitialisation entry points,
+          implemented in C or C++.  For example:</para>
+
+<programlisting>
+ HsBool mylib_init(void){
+   int argc = ...
+   char *argv[] = ...
+
+   // Initialize Haskell runtime
+   hs_init(&amp;argc, &amp;argv);
+
+   // Tell Haskell about all root modules
+   hs_add_root(__stginit_Foo);
+
+   // do any other initialization here and
+   // return false if there was a problem
+   return HS_BOOL_TRUE;
+ }
+
+ void mylib_end(void){
+   hs_exit();
+ }
+</programlisting>
+
+        <para>The intialisation routine, <literal>mylib_init</literal>, calls
+          <literal>hs_init()</literal> and <literal>hs_add_root()</literal> as
+          normal to initialise the Haskell runtime, and the corresponding
+          deinitialisation funtion <literal>mylib_end()</literal> calls
+          <literal>hs_exit()</literal> to shut down the runtime.</para>
+      </sect3>
+
+      <sect3 id="hs-exit">
+        <title>On the use of <literal>hs_exit()</literal></title>
+
+        <para><literal>hs_exit()</literal> normally causes the termination of
+          any running Haskell threads in the system, and when
+          <literal>hs_exit()</literal> returns, there will be no more Haskell
+          threads running.  The runtime will then shut down the system in an
+          orderly way, generating profiling
+          output and statistics if necessary, and freeing all the memory it
+          owns.</para>
+
+        <para>It isn't always possible to terminate a Haskell thread forcibly:
+          for example, the thread might be currently executing a foreign call,
+          and we have no way to force the foreign call to complete.  What's
+          more, the runtime must
+          assume that in the worst case the Haskell code and runtime are about
+          to be removed from memory (e.g. if this is a <link linkend="win32-dlls">Windows DLL</link>,
+          <literal>hs_exit()</literal> is normally called before unloading the
+          DLL).  So <literal>hs_exit()</literal> <emphasis>must</emphasis> wait
+          until all outstanding foreign calls return before it can return
+          itself.</para>
+
+        <para>The upshot of this is that if you have Haskell threads that are
+          blocked in foreign calls, then <literal>hs_exit()</literal> may hang
+          (or possibly busy-wait) until the calls return.  Therefore it's a
+          good idea to make sure you don't have any such threads in the system
+          when calling <literal>hs_exit()</literal>.  This includes any threads
+          doing I/O, because I/O may (or may not, depending on the
+          type of I/O and the platform) be implemented using blocking foreign
+          calls.</para>
+
+        <para>The GHC runtime treats program exit as a special case, to avoid
+          the need to wait for blocked threads when a standalone
+          executable exits.  Since the program and all its threads are about to
+          terminate at the same time that the code is removed from memory, it
+          isn't necessary to ensure that the threads have exited first.
+          (Unofficially, if you want to use this fast and loose version of
+          <literal>hs_exit()</literal>, then call
+          <literal>shutdownHaskellAndExit()</literal> instead).</para> 
       </sect3>
     </sect2>
     
@@ -299,7 +355,7 @@ int main(int argc, char *argv[])
       <indexterm><primary>C calls, function headers</primary></indexterm>
 
       <para>When generating C (using the <option>-fvia-C</option>
-      directive), one can assist the C compiler in detecting type
+      flag), one can assist the C compiler in detecting type
       errors by using the <option>-&num;include</option> directive
       (<xref linkend="options-C-compiler"/>) to provide
       <filename>.h</filename> files containing function
@@ -336,10 +392,10 @@ the module being compiled, you should supply all the <option>-&num;include</opti
 that you supplied when compiling the imported module.  If the imported module comes
 from another package, you won't necessarily know what the appropriate 
 <option>-&num;include</option> options are; but they should be in the package 
-configuration, which GHC knows about.  So if you are building a package, remember
-to put all those <option>-&num;include</option> options into the package configuration.
-See the <literal>c_includes</literal> field in <xref linkend="package-management"/>.
-</para>
+configuration, which GHC knows about.  So if you are building a package using
+        Cabal, remember to put all those include files in the package
+        description (see the <literal>includes</literal> field in the Cabal
+        documentation).</para>
 
 <para>
 It is also possible, according the FFI specification, to put the 
index 22a77de..f52f189 100644 (file)
@@ -210,8 +210,7 @@ make-sessions running under cygwin.
 
 <para>
 <emphasis>Making Haskell libraries into DLLs doesn't work on Windows at the
-moment; however, all the machinery is
-still there. If you're interested, contact the GHC team. Note that
+moment; we hope to re-instate this facility in the future.  Note that
 building an entire Haskell application as a single DLL is still supported: it's
        just multi-DLL Haskell programs that don't work.  The Windows
        distribution of GHC contains static libraries only.</emphasis></para>
@@ -403,13 +402,10 @@ non-static to static linking is simply a question of adding
 <title>Making DLLs to be called from other languages</title>
 
 <para>
-
 If you want to package up Haskell code to be called from other languages,
 such as Visual Basic or C++, there are some extra things it is useful to
-know. The dirty details are in the <emphasis>Foreign Function
-Interface</emphasis> definition, but it can be tricky to work out how to
-combine this with DLL building, so here's an example:
-
+know.  This is a special case of <xref linkend="ffi-library" />; we'll deal with
+          the DLL-specific issues that arise below.  Here's an example:
 </para>
 
 <itemizedlist>
@@ -521,6 +517,114 @@ the Haskell source and build the DLL.
 
 </sect2>
 
+<sect2>
+<title>Beware of DllMain()!</title>
+
+<para>The body of a <literal>DllMain()</literal> function is an
+extremely dangerous place! This is because the order in which DLLs are
+unloaded when a process is terminating is unspecified. This means that
+the <literal>DllMain()</literal> for your DLL may be called when other DLLs containing
+functions that you call when de-initializing your DLL have already
+been unloaded. In other words, you can't put shutdown code inside
+<literal>DllMain()</literal>, unless your shutdown code only requires use of certain
+functions which are guaranteed to be available (see the Platform SDK
+docs for more info).</para>
+
+<para>In particular, if you are writing a DLL that's statically
+linked with Haskell, it is not safe to call
+<literal>hs_exit()</literal> from <literal>DllMain()</literal>, since
+<literal>hs_exit()</literal> may make use of other DLLs (see also <xref
+          linkend="hs-exit" />).  What's more, if you
+wait until program shutdown to execute your deinitialisation code, Windows will have
+terminated all the threads in your program except the one calling
+<literal>DllMain()</literal>, which can cause even more
+problems.</para>
+
+<para>A solution is to always export <literal>Begin()</literal> and <literal>End()</literal> functions from your
+DLL, and call these from the application that uses the DLL, so that
+you can be sure that all DLLs needed by any shutdown code in your
+End() function are available when it is called.</para>
+
+<para>The following example is untested but illustrates the idea (please let us
+        know if you find problems with this example or have a better one).  Suppose we have a DLL called Lewis which makes use of 2
+Haskell modules <literal>Bar</literal> and <literal>Zap</literal>,
+where <literal>Bar</literal> imports <literal>Zap</literal> and is
+therefore the root module in the sense of <xref
+linkend="using-own-main" />. Then the main C++ unit for the DLL would
+look something like:</para>
+
+<programlisting>
+ // Lewis.cpp -- compiled using GCC
+ #include &lt;Windows.h&gt;
+ #include "HsFFI.h"
+
+ #define __LEWIS_DLL_EXPORT
+ #include "Lewis.h"
+
+ #include "Bar_stub.h"  // generated by GHC
+ #include "Zap_stub.h"
+
+ BOOL APIENTRY DllMain( HANDLE hModule, 
+                        DWORD  ul_reason_for_call, 
+                        LPVOID lpReserved
+                       ){
+   return TRUE;
+ }
+
+ extern "C"{
+
+ LEWIS_API HsBool lewis_Begin(){
+   int argc = ...
+   char *argv[] = ...
+
+   // Initialize Haskell runtime
+   hs_init(&amp;argc, &amp;argv);
+
+   // Tell Haskell about all root modules
+   hs_add_root(__stginit_Bar);
+
+   // do any other initialization here and
+   // return false if there was a problem
+   return HS_BOOL_TRUE;
+ }
+
+ LEWIS_API void lewis_End(){
+   hs_exit();
+ }
+
+ LEWIS_API HsInt lewis_Test(HsInt x){
+   // use Haskell functions exported by
+   // modules Bar and/or Zap
+
+   return ...
+ }
+
+ } // extern "C"
+
+and some application which used the functions in the DLL would have a main() function like:
+
+ // MyApp.cpp
+ #include "stdafx.h"
+ #include "Lewis.h"
+
+ int main(int argc, char *argv[]){
+   if (lewis_Begin()){
+      // can now safely call other functions
+      // exported by Lewis DLL
+
+   }
+   lewis_End();
+   return 0;
+ }
+</programlisting>
+
+<para><literal>Lewis.h</literal> would have to have some appropriate <literal>#ifndef</literal> to ensure that the
+Haskell FFI types were defined for external users of the DLL (who
+wouldn't necessarily have GHC installed and therefore wouldn't have
+the include files like <literal>HsFFI.h</literal> etc). 
+</para>
+</sect2>
+
 </sect1>
 </chapter>