summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSimon Marlow <marlowsd@gmail.com>2010-10-14 08:42:53 +0000
committerSimon Marlow <marlowsd@gmail.com>2010-10-14 08:42:53 +0000
commit0a435635320c2fb075694b52ddbce5bb792110f5 (patch)
tree80ef4b02b8039a37d4acba656e2c43e87ff54a3f
parentf18399d395446674e7da58bdd8c4311fac4d799e (diff)
downloadhaskell-0a435635320c2fb075694b52ddbce5bb792110f5.tar.gz
Add more documentation for interruptible foreign calls
-rw-r--r--docs/users_guide/ffi-chap.xml82
1 files changed, 81 insertions, 1 deletions
diff --git a/docs/users_guide/ffi-chap.xml b/docs/users_guide/ffi-chap.xml
index b33e95abb6..2e6ce2f372 100644
--- a/docs/users_guide/ffi-chap.xml
+++ b/docs/users_guide/ffi-chap.xml
@@ -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">