
So I did a writeup of what I thought might be the next direction to go with the interruptible patch: http://blog.ezyang.com/2010/09/towards-platform-agnostic-interruptibility/ The really interesting bit (which I didn't cover) is what information to give to the user functioSo I did a writeup of what I thought might be the next direction to go with the interruptible patch: http://blog.ezyang.com/2010/09/towards-platform-agnostic-interruptibility/ The really interesting bit (which I didn't cover) is what information to give to the user function. It needs to be somewhat under the hood: if someone wants to pthread_cancel they need to know what the pthreads ID is; if they want to transmit a Windows event they need some way to get a hold of the event handle associated with the foreign call. Edward

On 11/09/2010 07:59, Edward Z. Yang wrote:
So I did a writeup of what I thought might be the next direction to go with the interruptible patch:
http://blog.ezyang.com/2010/09/towards-platform-agnostic-interruptibility/
The really interesting bit (which I didn't cover) is what information to give to the user functioSo I did a writeup of what I thought might be the next direction to go with the interruptible patch:
http://blog.ezyang.com/2010/09/towards-platform-agnostic-interruptibility/
The really interesting bit (which I didn't cover) is what information to give to the user function. It needs to be somewhat under the hood: if someone wants to pthread_cancel they need to know what the pthreads ID is; if they want to transmit a Windows event they need some way to get a hold of the event handle associated with the foreign call.
The idea of having user-definable cancellation mechanisms seems quite sensible, given that we have so many ways to do this. However it seems quite hard in practice: for pthread_cancel, the RTS has to behave quite differently from pthread_kill. The API for defining the cancellation mechanism could get quite complicated. For now I would go with 'interruptible' (meaning either pthread_kill() or CancelSynchronousIO()). It's not nearly as dangerous as pthread_cancel(), but it covers a lot of the cases we're interested in, and it doesn't have problems with bound threads. Cheers, Simon

Excerpts from Simon Marlow's message of Mon Sep 13 05:10:13 -0400 2010:
The idea of having user-definable cancellation mechanisms seems quite sensible, given that we have so many ways to do this. However it seems quite hard in practice: for pthread_cancel, the RTS has to behave quite differently from pthread_kill. The API for defining the cancellation mechanism could get quite complicated.
For now I would go with 'interruptible' (meaning either pthread_kill() or CancelSynchronousIO()). It's not nearly as dangerous as pthread_cancel(), but it covers a lot of the cases we're interested in, and it doesn't have problems with bound threads.
Sounds good. I'll roll this change tomorrow. Maybe we should emit a warning pre-Vista that "interruptible" is not being honored? Also, it occurs to me that a lot of this functionality could be implemented in user space. Cheers, Edward

On 15/09/2010 03:33, Edward Z. Yang wrote:
Excerpts from Simon Marlow's message of Mon Sep 13 05:10:13 -0400 2010:
The idea of having user-definable cancellation mechanisms seems quite sensible, given that we have so many ways to do this. However it seems quite hard in practice: for pthread_cancel, the RTS has to behave quite differently from pthread_kill. The API for defining the cancellation mechanism could get quite complicated.
For now I would go with 'interruptible' (meaning either pthread_kill() or CancelSynchronousIO()). It's not nearly as dangerous as pthread_cancel(), but it covers a lot of the cases we're interested in, and it doesn't have problems with bound threads.
Sounds good. I'll roll this change tomorrow. Maybe we should emit a warning pre-Vista that "interruptible" is not being honored?
It's not clear to me when to emit the warning: the system we're compiling on is not necessarily the one we're going to run on. This is more often the case for us where we're building distributions, than for other people though.
Also, it occurs to me that a lot of this functionality could be implemented in user space.
Maybe - feel free to propose something... Cheers, Simon

Excerpts from Simon Marlow's message of Wed Sep 15 04:34:06 -0400 2010:
It's not clear to me when to emit the warning: the system we're compiling on is not necessarily the one we're going to run on. This is more often the case for us where we're building distributions, than for other people though.
That's true; we'd only be able to test at runtime using GetProcAddress, and we shouldn't really emit extra output unless specifically asked for (maybe as an RTS option). But, as you say, an appropriately phrased compile time check might be useful.
Maybe - feel free to propose something...
Essentially, you never throw exceptions at Haskell threads actually running FFI calls; you through them at "management" threads that then take appropriate action on the real thread. In order to allow for unsafe thread termination, there'd need to be a way to extra the true thread identifier from the Haskell thread, but other mechanisms could just be implemented with more FFI calls. Edward

There are some invariants that are being violated by pthread_kill(id, SIGINT) and I'm having difficulty understanding them. I get the following errors: cd ./concurrent/should_run && '/home/ezyang/Dev/ghc/inplace/bin/ghc-stage2' -fforce-recomp -dcore-lint -dcmm-lint -no-user-package-conf -rtsopts -dno-debug-output -o foreignInterruptible foreignInterruptible.hs -threaded -debug >foreignInterruptible.comp.stderr 2>&1 cd ./concurrent/should_run && ./foreignInterruptible foreignInterruptible.run.stdout 2>foreignInterruptible.run.stderr Wrong exit code (expected 0 , actual 134 ) Stdout: Stderr: foreignInterruptible: internal error: WEAK object entered! (GHC version 6.13.20100908 for i386_unknown_linux) Please report this as a GHC bug: http://www.haskell.org/ghc/reportabug Aborted (core dumped) *** unexpected failure for foreignInterruptible(threaded1) Even more curiously, though, if I hand-run the command I don't get any problems. Edward

It looks like the problem was that the default handler for SIGINT was scheduling code to run, when we really just wanted to get EINTR. I'm sketchily using SIGPIPE right now; maybe we should use SIGUSR1 or something. Edward

Here's what the Windows version would look like (if I could get HEAD to build, that is :-) void interruptOSThread (OSThreadId id) { HANDLE hdl; PCSIO pCSIO; if (!(hdl = OpenThread(THREAD_TERMINATE,FALSE,id))) { sysErrorBelch("interruptOSThread: OpenThread"); stg_exit(EXIT_FAILURE); } pCSIO = (PCSIO) GetProcAddress(GetModuleHandle(TEXT("Kernel32.dll")), "CancelSynchronousIo"); if ( NULL != pCSIO ) { pCSIO(hdl); } else { // Nothing to do, unfortunately } } Cheers, Edward
participants (2)
-
Edward Z. Yang
-
Simon Marlow