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