darcs patch: Interruptible FFI calls with pthread_kill and
CancelSy...
Simon Marlow
marlowsd at gmail.com
Fri Sep 24 08:52:39 EDT 2010
On 19/09/2010 01:31, Edward Z. Yang wrote:
> + case BlockedOnCCall_Interruptible:
> +#ifdef THREADED_RTS
> + {
> + Task *task = NULL;
> + // walk suspended_ccalls to find the correct worker thread
> + InCall *incall;
> + for (incall = cap->suspended_ccalls; incall != NULL; incall = incall->next) {
> + if (incall->suspended_tso == target) {
> + task = incall->task;
> + break;
> + }
> + }
> + if (task != NULL) {
> + raiseAsync(cap, target, msg->exception, rtsFalse, NULL);
> + interruptWorkerTask(task);
> + return THROWTO_SUCCESS;
> + } else {
> + debugTraceCap(DEBUG_sched, cap, "throwTo: could not find worker thread to kill");
> + }
> + // fall to next
> + }
> +#endif
This isn't quite right:
- we want to queue up the exception unconditionally,
instead of calling raiseAsync
- we should not call interruptWorkerTask if
TSO_BLOCKEX && !TSO_INTERRUPTIBLE
(so that you can use maskUninterruptible around an interruptible
foreign call).
so pthread_kill() will bump the foreign call out of its blocking state,
causing it to return to the RTS at which point the exception will be
raised. If for some reason pthread_kill() doesn't cause the foreign
call to return, then we don't want the exception to have been already
raised, that could cause confusion later (it was ok before when we were
killing the thread making the call, but not now that we're just prodding
it).
Now, one thing I've noticed is that in resumeThread() we call
awakenBlockedExceptionQueue(), but to make this work properly we
probably need to call maybePerformBlockedException() instead, otherwise
the thread will carry on for a bit before being struck down. I don't
know why we're not calling maybePerformBlockedException(), but I imagine
you'll find out if you try it :-)
Cheers,
Simon
More information about the Cvs-ghc
mailing list