Let's start Scheme

2015-08-06

Safer thread termination (2)

I think I've found a (imperfect) solution to do it.

Goal


The goal is pretty simple. No crash, that's it. Optionally, releasing resource as much as possible. But the resource in this case is not about Scheme world or Sagittarius created, it's OS resource such as allocated stack or so.

The problem


Yes, it's the problem. The problem was sometimes it crashed with 0xC0000005 (access violation, SEGV in POSIX way). The termination process was described in previous article (Safer thread termination) . The cause, in short, was interrupting Eip or Rip may break call stack frame.

As my conclusion, if the Scheme process went into deep inside of C function call, then the program counter is overwritten, the call stack may get broke. So when the process tries to return from RaiseException however there is no place to return or returning invalid address. (This may not be true but seems like it.)

Comparing stack pointer was not enough


In previous article, I've written to do it. It does prevent the error when the thread has already returned from entry point however it didn't resolve returning from deep stack address. So I need to find one more thing.

The issue is breaking call stack. Means, if I can restore it until the thread entry function is called, then the call stack is not broken and can return properly.

jmp_buf?


If I need to restore the stack frame of certain point, then setjmp and longjmp seem the things I need to use, instead of calling RaiseException. So I've put setjmp before calling Scheme world process. Then the thread-terminate! interrupts the process to the C function which calls longjmp.

Not a perfect solution


Unfortunately, this isn't a perfect solution. It works most of the time and, I think, should be good enough (so far I don't get crash in my test case). However, the following code may not work:
(thread-terminate! (thread-start! (make-thread (lambda () #t))))
The problem of this piece of code is that the thread may not be terminated. If the thread couldn't reach the point where setjmp is called, then thread-terminate! would call longjmp without proper jmp_buf. Or the thread wouldn't be terminated if it didn't reach the internal thread entry point. Who writes this crap? Who knows.

This may not be a perfect solution but at least less possibility to get crashed. Thus it's safer than before. So, for now, I'm happy with it.

No comments:

Post a Comment