Win VM modifications
Rob Gayvert
rtg at rochester.rr.com
Wed Mar 9 15:18:29 UTC 2005
Andreas Raab wrote:
>> I just tried out a test that demonstrates that the real culprit is
>> the callback mechanism. I stripped out all of the wx initialization,
>> event processes, and wx event processing from my image and vm, so it
>> should be possible to reproduce this with a stock image. Here's the
>> setup.
>
> The first question coming to my mind is: Does wx use any kind of
> exception handling? IIRC, then wx is C++ right?! If so, exception
> handling might play a significantly different role here.
Yes, wx is definitely C++. But it doesn't use exception handling itself:
http://www.wxwidgets.org/manuals/2.5.3/wx_exceptionsoverview.html
>> In the VM, a callback is initiated with:
>>
>> interpreterProxy->signalSemaphoreWithIndex(semaIndex);
>> if (setjmp(jmpbuf) == 0) {
>> interpret();
>> }
>
> That too. Except that (with multiple callbacks) one would expect that
> jmpbuf is dynamically allocated and passed to the supporting call to
> "Wx returnFromCallback" somehow...
Yes, this example is slightly simplified. But I have only one handler
for all wx events, so the jmpbufs are statically allocated, with one for
each level of recursion on interpret().
>> The results:
>>
>> 1. If the callback is initiated from Squeak by a primitive call, it
>> can be called any number of times without a problem.
>>
>> 2. If the callback is initiated periodically (say once per second)
>> from ioProcessEvents, it dies very predictably after 15 iterations.
>
> If correct, this is indeed interesting (and fixable if need be). But
> what exactly qualifies as "being initiated by a primitive call"? E.g.,
> in almost all situation ioProcessEvents is called when a primitive is
> called (the rare exception are true interrupt checks for long-taking
> primitives). Or do you have "special" primitives in mind?
I should have said "external primitive"; that is, a call to a simple
function in my WxPlugin that signals the semaphore and calls
interpret(). I added a trace to see how ioProcessEvents was being
entered, and you're correct -- in this test, most of the time it comes
from the primitive ioRelinquishProcessorForMicroseconds, with a few
scattered occurrences of ioGetNextEvent and the commonSend section of
the interpreter loop.
But I misstated one important detail in this test: the results are valid
only if the callback loop in Squeak is forked at highestPriority. At
normal priority, (1) crashes also.
And here's another interesting tidbit. If I lengthen the callback
interval in (2), it will go on much longer. But the instant I try to
bring up a process browser, it crashes.
So this suggests something is amiss with processes and the re-entrant
call to interpret(). Some time ago I tried to exert more control over
what happens here by suspending the current process before calling
interpret(), and then resuming this process after the
returnFromCallback. This improved matters somewhat, but still
occasionally crashed.
I think all of this is also related to a secondary problem: if I try to
return a value directly from a wx primitive that indirectly kicks off a
callback (e.g., WxFrame>>createStatusBar causes an #onSize event before
it returns), the return value is usually wrong. I've worked around this
by having all of the wx primitives set their return values in static
location, which are then retrieved with a second primitive call, but
this shouldn't be necessary.
My guess is that someone's stack may get messed up if the callback
process is not the first process when interpret() is re-entered. Does
that sound plausible?
More information about the Wxsqueak
mailing list