Let's start Scheme

2015-08-04

Safer thread termination

Terminating a thread is a dangerous operation (AFAIK). So this shouldn't be done in general. However I've wrote the library (util concurrent) which uses thread-terminate! to finish tasks forcibly. As my understanding, as long as you free all resources held by the thread, terminating thread isn't that badly wrong. Well, if this was the conclusion, then I wouldn't write this. It actually works fine on POSIX environments I usually test, including Cygwin, however not working properly on Windows.

Windows has the API which terminates a thread, called TerminateThread. I, however, don't use this because of the following reasons:
  • It may not release all resources
  • There is no way to handle after termination
If the resource aren't released, then it may leak eventually. I don't use Sagittarius on 24/7 service so this might be a trivial issue but you'll never know. So it's better to have as safe as possible.

If you don't use TerminateThread, then there's, afaik, not many choice to do it. The way I've chosen is using CONTEXT. The basic process is the followings:
  1. Suspend the target thread
  2. Check if it's active
  3. Get thread context
  4. Set program counter to the function calls RaiseException
  5. Resume the thread
The thread caller wraps the thread function with _try and _except, so the thrown exception will be caught.

Until here, there seems nothing wrong and works fine. Well no. This works most of the case however at some point you may get a context which contains no call frame of thread caller function. I think this means either thread is almost terminating or it's finished but still active. Then you'd get access violation error.

Now, what can I do? I think I'll try to compare stack pointer. Luckly, Boehm GC has base stack pointer on each thread. So if I can get this and compare with the thread context stack pointer, I might be able to detect if the thread is already finished (or at least returned from the thread function of Sagittarius) or not.

If you know better way, please let me know.

2 comments:

Shiro Kawai said...

Very interesting. I wonder if it's safe when the thread you suspend is in middle of unwinding
exception handlers.

kei said...

I think suspension itself is safe (though, may cause dead lock according to MSDN). The rest of the operation is not, unfortunately. I'm still getting occasional unexpected error (and crash).

Unwinding exception/invoking continuation captured outside of the thread can be unsafe but as long as in the Scheme world, I'd throw the responsibility to users. (terminating a thread is not a safe operation anyway.)

Post a Comment