<div dir="ltr">Hi Nicolas, Hi Esteban,<div class="gmail_extra"><br><div class="gmail_quote">On Sun, Mar 12, 2017 at 6:31 AM, Nicolas Cellier <span dir="ltr"><<a href="mailto:nicolas.cellier.aka.nice@gmail.com" target="_blank">nicolas.cellier.aka.nice@gmail.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"> <br><div dir="ltr"><div><div>Ah, and the example does not work better in 32bits pharo, so no need to invoke a 64 bits problem.<br><br></div>Also, at image startup, there's a gray background. And last time I restarted the 32bits image, here is the kind of artefacts I got at first menu click:<br><br><img src="cid:ii_15ac2b73e65d918f" alt="Images intégrées 1" width="451" height="344"><br><br></div>IMO, all your image startup problem (like crash at startup) are related.<br></div></blockquote><div><br></div><div>[At the end of my message is something important for the author and maintainers of AthensCairoSurface class; if you're that person please read the end of my message, point c) below].</div><div><br></div><div><br></div><div>I agree. I think that callbacks are very important. Yesterday I reimplemented ownVM: and disownVM: for the non-threaded standard configuration (our current VMs) to preserve the argumentCount variable across the callback. argumentCount is used by many primitives (via interpreterProxy methodArgumentCount) to cut-back the arguments on returning from the primitive (other primitives use a consent if they know what their argument count is). Without doing this the argumentCount variable will be changed by the interpreter sends or interpreter primitives executed during a callback, and on return may be completely different from the value it had in the primitive that executed the callback(s). Hence when the primitive that executes a callback tries to return it may pop the wrong number pif values off of the stack.</div><div><br></div><div>I fixed this so that ownVM, called when a callback is initiated, remembers the argumentCount and answers it encoded as the result of ownVM. diwownVM is called when the callback returns to C and is given the result of ownVM as an argument. So disownVM restores argumentCount to its value before the callback, which is presumably the right value for the primitive that is executing the callback. [Note that in the threaded VM the argumentCount /and/ newMethod are remembered in per-thread data and restored when a thread takes ownership of the VM; i.e. in the threaded VM it does the right thing (tm) ].</div><div><br></div><div>Fixing this had several effects. First the screen was a normal size, with a black background except in the VGTigerDemo screen area, second, the garbage pixels at the bottom of the screen disappeared, finally the crash happens regularly on the third complete revolution of the tiger's head. Here's the VM code (I'll commit soon):</div><div><br></div><div>StackInterpreter>>ownVM: threadIndexAndFlags</div><div><span class="gmail-Apple-tab-span" style="white-space:pre"> </span><api></div><div><span class="gmail-Apple-tab-span" style="white-space:pre"> </span><inline: false></div><div><span class="gmail-Apple-tab-span" style="white-space:pre"> </span>"This is the entry-point for plugins and primitives that wish to reacquire the VM after having</div><div><span class="gmail-Apple-tab-span" style="white-space:pre"> </span> released it via disownVM or callbacks that want to acquire it without knowing their ownership</div><div><span class="gmail-Apple-tab-span" style="white-space:pre"> </span> status. While this exists for the threaded FFI VM we use it to reset the argumentCount after a callback.</div><div><br></div><div><span class="gmail-Apple-tab-span" style="white-space:pre"> </span> Answer the argumentCount encoded as a SmallInteger if the current thread is the VM thread.</div><div><span class="gmail-Apple-tab-span" style="white-space:pre"> </span> Answer -1 if the current thread is unknown to the VM and fails to take ownership."</div><div><span class="gmail-Apple-tab-span" style="white-space:pre"> </span>| amInVMThread |</div><div><span class="gmail-Apple-tab-span" style="white-space:pre"> </span><var: 'amInVMThread' declareC: 'extern sqInt amInVMThread(void)'></div><div><span class="gmail-Apple-tab-span" style="white-space:pre"> </span>self cCode: [] inSmalltalk: [amInVMThread := 1. amInVMThread class].</div><div><span class="gmail-Apple-tab-span" style="white-space:pre"> </span>self amInVMThread ifFalse:</div><div><span class="gmail-Apple-tab-span" style="white-space:pre"> </span>[^-1].</div><div><span class="gmail-Apple-tab-span" style="white-space:pre"> </span>self assert: primFailCode = 0.</div><div><span class="gmail-Apple-tab-span" style="white-space:pre"> </span>^objectMemory integerObjectOf: argumentCount</div><div><br></div><div>StackInterpreter>>disownVM: flags<br></div><div><span class="gmail-Apple-tab-span" style="white-space:pre"> </span><api></div><div><span class="gmail-Apple-tab-span" style="white-space:pre"> </span><inline: false></div><div><span class="gmail-Apple-tab-span" style="white-space:pre"> </span>"Release the VM to other threads and answer the current thread's index.</div><div><br></div><div><span class="gmail-Apple-tab-span" style="white-space:pre"> </span> This is the entry-point for plugins and primitives that wish to release the VM while</div><div><span class="gmail-Apple-tab-span" style="white-space:pre"> </span> performing some operation that may potentially block, and for callbacks returning</div><div><span class="gmail-Apple-tab-span" style="white-space:pre"> </span> back to some blocking operation. While this exists for the threaded FFI VM we use</div><div><span class="gmail-Apple-tab-span" style="white-space:pre"> </span> it to reset the argumentCount after a callback."</div><div><span class="gmail-Apple-tab-span" style="white-space:pre"> </span>self assert: ((objectMemory isIntegerObject: flags)</div><div><span class="gmail-Apple-tab-span" style="white-space:pre"> </span>and: [(objectMemory integerValueOf: flags)</div><div><span class="gmail-Apple-tab-span" style="white-space:pre"> </span>between: 0</div><div><span class="gmail-Apple-tab-span" style="white-space:pre"> </span>and: (self argumentCountOfMethodHeader: -1)]).</div><div><span class="gmail-Apple-tab-span" style="white-space:pre"> </span>self assert: primFailCode = 0.</div><div><span class="gmail-Apple-tab-span" style="white-space:pre"> </span>argumentCount := objectMemory integerValueOf: flags.</div><div><span class="gmail-Apple-tab-span" style="white-space:pre"> </span>^0</div><div><br></div><div>and this is the code in thunkEntry (the callback entry-point) that calls ownVM: and then disownVM:</div><div><br></div><div><div>long</div><div>thunkEntry(void *thunkp, sqIntptr_t *stackp)</div><div>{</div><div> VMCallbackContext vmcc;</div><div> VMCallbackContext *previousCallbackContext;</div><div> int flags, returnType;</div><div>...</div><div> if ((flags = interpreterProxy->ownVM(0)) < 0) {</div><div> fprintf(stderr,"Warning; callback failed to own the VM\n");</div><div> return -1;</div><div> }</div><div><br></div><div> if (!(returnType = setjmp(vmcc.trampoline))) {</div><div> previousCallbackContext = getRMCC();</div><div> setRMCC(&vmcc);</div><div> vmcc.thunkp = thunkp;</div><div> vmcc.stackp = stackp + 2; /* skip address of retpc & retpc (thunk) */</div><div> vmcc.intregargsp = 0;</div><div> vmcc.floatregargsp = 0;</div><div> interpreterProxy->sendInvokeCallbackContext(&vmcc);</div><div>...</div><div> }<br></div><div> setRMCC(previousCallbackContext);</div><div> interpreterProxy->disownVM(flags);</div></div><div><br></div><div><div> switch (returnType) {</div><div><br></div><div> case retword: return vmcc.rvs.valword;</div></div><div>...</div><div><br></div><div>So while I have no fix for the bug,</div><div><br></div><div>a) I understand that there is a serious issue with callbacks not restoring sufficient state on return from callback (ideally both argumentCOunt /and/ newMethod should be preserved iff a primitive invoking a callback can fail after invoking a callback, but this is a /really/ bad idea; primitives should only fail if they have no effects, so this isn't an important issue; restoring argumentCOunt is essential and my fix does that).</div><div><br></div><div>b) the crash is now 100% repeatable and happens always on the third rotation of the tiger's head, so I'm optimistic I can understand the bug</div><div><br></div><div>c) the code that creates the callbacks waste cycles installing showSurface and unlockSurface callbacks that do nothing. Instead both createUnlockSurfaceFn and createShowSurfaceFn should simply answer 0. These callbacks don't need to happen and callbacks are complex enough that avoiding two of the three calklbacks involved in a bitblt could speed things up.</div><div><br></div><div>More info as I have it.</div><div><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><div dir="ltr"></div><div class="gmail_extra"><br><div class="gmail_quote">2017-03-12 13:43 GMT+01:00 Nicolai Hess <span dir="ltr"><<a href="mailto:nicolaihess@gmail.com" target="_blank">nicolaihess@gmail.com</a>></span>:<br><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"> <br><div dir="ltr"><br><div class="gmail_extra"><br><div class="gmail_quote">2017-03-12 13:36 GMT+01:00 Nicolas Cellier <span dir="ltr"><<a href="mailto:nicolas.cellier.aka.nice@gmail.com" target="_blank">nicolas.cellier.aka.nice@gmai<wbr>l.com</a>></span>:<br><blockquote style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-style:solid;border-left-color:rgb(204,204,204);padding-left:1ex" class="gmail_quote"> <br><div dir="ltr">Couldn't it be that some Smalltalk memory has been relocated? (I'm thinking of the DisplayScreen bits)<br></div></blockquote><div><br><a href="http://forum.world.st/Too-frequent-crashes-tp4927143p4927722.html" target="_blank">http://forum.world.st/Too-freq<wbr>uent-crashes-tp4927143p4927722<wbr>.html</a><br><br><br> </div><blockquote style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-style:solid;border-left-color:rgb(204,204,204);padding-left:1ex" class="gmail_quote"><div dir="ltr"></div><div class="gmail_extra"><br><div class="gmail_quote">2017-03-12 12:53 GMT+01:00 Esteban Lorenzano <span dir="ltr"><<a href="mailto:estebanlm@gmail.com" target="_blank">estebanlm@gmail.com</a>></span>:<br><blockquote style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-style:solid;border-left-color:rgb(204,204,204);padding-left:1ex" class="gmail_quote"> <br><div style="word-wrap:break-word">Hi, <div><br></div><div>this is lockSurfaceFn: </div><div><br></div><div><div>createLockSurfaceFn</div><div><span style="white-space:pre-wrap" class="gmail-m_-740808584047858393m_4759342666489130635gmail-m_-7780002836349848460m_-4906969583213588979Apple-tab-span"> </span>^ FFICallback </div><div><span style="white-space:pre-wrap" class="gmail-m_-740808584047858393m_4759342666489130635gmail-m_-7780002836349848460m_-4906969583213588979Apple-tab-span"> </span>signature: #(void * (void *handle, int *pitch, int x, int y, int w, int h))</div><div><span style="white-space:pre-wrap" class="gmail-m_-740808584047858393m_4759342666489130635gmail-m_-7780002836349848460m_-4906969583213588979Apple-tab-span"> </span>block: [ :handle :pitch :x :y :w :h |</div><div><span style="white-space:pre-wrap" class="gmail-m_-740808584047858393m_4759342666489130635gmail-m_-7780002836349848460m_-4906969583213588979Apple-tab-span"> </span>pitch signedLongAt: 1 put: (self get_stride: handle).</div><div><span style="white-space:pre-wrap" class="gmail-m_-740808584047858393m_4759342666489130635gmail-m_-7780002836349848460m_-4906969583213588979Apple-tab-span"> </span>self get_data: handle ]</div></div><div><br></div><div>and</div><div><br></div><div><div>createUnlockSurfaceFn</div><div><span style="white-space:pre-wrap" class="gmail-m_-740808584047858393m_4759342666489130635gmail-m_-7780002836349848460m_-4906969583213588979Apple-tab-span"> </span>^ FFICallback </div><div><span style="white-space:pre-wrap" class="gmail-m_-740808584047858393m_4759342666489130635gmail-m_-7780002836349848460m_-4906969583213588979Apple-tab-span"> </span>signature: #(int (void *handle, int x, int y, int w, int h))</div><div><span style="white-space:pre-wrap" class="gmail-m_-740808584047858393m_4759342666489130635gmail-m_-7780002836349848460m_-4906969583213588979Apple-tab-span"> </span>block: [ :handle :x :y :w :h | 0 "Do nothing” ]</div></div><div><br></div><div>cheers!</div><div>Esteban</div><div><br><div><blockquote type="cite"><div>On 12 Mar 2017, at 03:34, Eliot Miranda <<a href="mailto:eliot.miranda@gmail.com" target="_blank">eliot.miranda@gmail.com</a>> wrote:</div><br class="gmail-m_-740808584047858393m_4759342666489130635gmail-m_-7780002836349848460m_-4906969583213588979Apple-interchange-newline"><div><div style="font-family:helvetica;font-size:12px;font-style:normal;font-variant-caps:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px" dir="ltr">Hi Esteban,<div class="gmail_extra"><br><div class="gmail_quote">On Fri, Mar 10, 2017 at 7:35 AM, Esteban Lorenzano<span class="gmail-m_-740808584047858393m_4759342666489130635gmail-m_-7780002836349848460m_-4906969583213588979Apple-converted-space"> </span><span dir="ltr"><<a href="mailto:estebanlm@gmail.com" target="_blank">estebanlm@gmail.com</a><wbr>></span><span class="gmail-m_-740808584047858393m_4759342666489130635gmail-m_-7780002836349848460m_-4906969583213588979Apple-converted-space"> </span>wrote:<br><blockquote style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-style:solid;border-left-color:rgb(204,204,204);padding-left:1ex" class="gmail_quote"><br>Hi,<br><br>I’m tumbling into an error in Pharo, because we use callbacks intensively, in Athens(cairo)-to-World conversion in particular, and people is sending always their crash reports… we made the whole conversion a lot more robust since problems started to arise, but now I hit a wall I cannot solve: I think problem is in something in callbacks.<br></blockquote><div><br></div><div>My original theory is wrong. As you suspected it is something to do with the callback in primitiveCopyBits via lockSurfaces & unlockSurfaces. Can you tell me what the callback is and what code installs it into the lockSurfaceFn and unlockSurfaceFn?</div><div><br></div><blockquote style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-style:solid;border-left-color:rgb(204,204,204);padding-left:1ex" class="gmail_quote"><br>And problem is showing very easy on 64bits (while in 32bits it takes time and is more random).<br><br>Here is the easiest way to reproduce it (in mac):<br><br>wget<span class="gmail-m_-740808584047858393m_4759342666489130635gmail-m_-7780002836349848460m_-4906969583213588979Apple-converted-space"> </span><a rel="noreferrer" href="http://files.pharo.org/get-files/60/pharo64-mac-latest.zip" target="_blank">files.pharo.org/get-files<wbr>/60/pharo64-mac-latest.zip</a><br>wget<span class="gmail-m_-740808584047858393m_4759342666489130635gmail-m_-7780002836349848460m_-4906969583213588979Apple-converted-space"> </span><a rel="noreferrer" href="http://files.pharo.org/get-files/60/pharo64.zip" target="_blank">files.pharo.org/get-files<wbr>/60/pharo64.zip</a><br>wget<span class="gmail-m_-740808584047858393m_4759342666489130635gmail-m_-7780002836349848460m_-4906969583213588979Apple-converted-space"> </span><a rel="noreferrer" href="http://files.pharo.org/get-files/60/sources.zip" target="_blank">files.pharo.org/get-files<wbr>/60/sources.zip</a><br>unzip pharo64-mac-latest.zip<br>unzip pharo64.zip<br>unzip sources.zip<br>./Pharo.app/Contents/MacOS/Pha<wbr>ro ./Pharo64-60438.image eval "VGTigerDemo runDemo"<br><br>eventually (like 5-6 seconds after, if not immediately), you will have a stack like this:<br><br>SmallInteger(Object)>>primitiv<wbr>eFailed:<br>SmallInteger(Object)>>primitiv<wbr>eFailed<br>SmallInteger(VMCallbackContext<wbr>64)>>primSignal:andReturnAs:fr<wbr>omContext:<br>GrafPort>>copyBits<br>GrafPort>>image:at:sourceRect:<wbr>rule:<br>FormCanvas>>image:at:sourceRec<wbr>t:rule:<br>FormCanvas(Canvas)>>drawImage:<wbr>at:sourceRect:<br>FormCanvas(Canvas)>>drawImage:<wbr>at:<br>VGTigerDemo>>runDemo<br>VGTigerDemo class>>runDemo<br>UndefinedObject>>DoIt<br>OpalCompiler>>evaluate<br>OpalCompiler(AbstractCompiler)<wbr>>>evaluate:<br>[ result := Smalltalk compiler evaluate: aStream.<br>self hasSessionChanged<br> <span class="gmail-m_-740808584047858393m_4759342666489130635gmail-m_-7780002836349848460m_-4906969583213588979Apple-converted-space"> </span>ifFalse: [ self stdout<br> <span class="gmail-m_-740808584047858393m_4759342666489130635gmail-m_-7780002836349848460m_-4906969583213588979Apple-converted-space"> </span>print: result;<br> <span class="gmail-m_-740808584047858393m_4759342666489130635gmail-m_-7780002836349848460m_-4906969583213588979Apple-converted-space"> </span>lf ] ] in EvaluateCommandLineHandler>>ev<wbr>aluate: in Block: [ result := Smalltalk compiler evaluate: aStream....<br>BlockClosure>>on:do:<br>EvaluateCommandLineHandler>>ev<wbr>aluate:<br>EvaluateCommandLineHandler>>ev<wbr>aluateArguments<br>EvaluateCommandLineHandler>>ac<wbr>tivate<br>EvaluateCommandLineHandler class(CommandLineHandler class)>>activateWith:<br>[ aCommandLinehandler activateWith: commandLine ] in PharoCommandLineHandler(BasicC<wbr>ommandLineHandler)>>activateSu<wbr>bCommand: in Block: [ aCommandLinehandler activateWith: commandLine ]<br>BlockClosure>>on:do:<br>PharoCommandLineHandler(BasicC<wbr>ommandLineHandler)>>activateSu<wbr>bCommand:<br>PharoCommandLineHandler(BasicC<wbr>ommandLineHandler)>>handleSubc<wbr>ommand<br>PharoCommandLineHandler(BasicC<wbr>ommandLineHandler)>>handleArgu<wbr>ment:<br>[ self<br> <span class="gmail-m_-740808584047858393m_4759342666489130635gmail-m_-7780002836349848460m_-4906969583213588979Apple-converted-space"> </span>handleArgument:<br> <span class="gmail-m_-740808584047858393m_4759342666489130635gmail-m_-7780002836349848460m_-4906969583213588979Apple-converted-space"> </span>(self arguments<br> <span class="gmail-m_-740808584047858393m_4759342666489130635gmail-m_-7780002836349848460m_-4906969583213588979Apple-converted-space"> </span>ifEmpty: [ '' ]<br> <span class="gmail-m_-740808584047858393m_4759342666489130635gmail-m_-7780002836349848460m_-4906969583213588979Apple-converted-space"> </span>ifNotEmpty: [ :arguments | arguments first ]) ] in PharoCommandLineHandler(BasicC<wbr>ommandLineHandler)>>activate in Block: [ self...<br>BlockClosure>>on:do:<br>PharoCommandLineHandler(BasicC<wbr>ommandLineHandler)>>activate<br>PharoCommandLineHandler>>activ<wbr>ate<br>PharoCommandLineHandler class(CommandLineHandler class)>>activateWith:<br>[ super activateWith: aCommandLine ] in PharoCommandLineHandler class>>activateWith: in Block: [ super activateWith: aCommandLine ]<br><br>Any idea?<br><br>thanks!<br><span class="gmail-m_-740808584047858393m_4759342666489130635gmail-m_-7780002836349848460m_-4906969583213588979HOEnZb"><font color="#888888">Esteban</font></span></blockquote></div><br><br clear="all"><div><br></div>--<span class="gmail-m_-740808584047858393m_4759342666489130635gmail-m_-7780002836349848460m_-4906969583213588979Apple-converted-space"> </span><br><div class="gmail-m_-740808584047858393m_4759342666489130635gmail-m_-7780002836349848460m_-4906969583213588979gmail_signature"><div dir="ltr"><div><span style="font-size:small;border-collapse:separate"><div>_,,,^..^,,,_<br></div><div>best, Eliot</div></span></div></div></div></div></div></div></blockquote></div><br></div></div><br></blockquote></div><br></div>
<br></blockquote></div><br></div></div>
<br></blockquote></div><br></div>
<br></blockquote></div><br><br clear="all"><div><br></div>-- <br><div class="gmail_signature"><div dir="ltr"><div><span style="font-size:small;border-collapse:separate"><div>_,,,^..^,,,_<br></div><div>best, Eliot</div></span></div></div></div>
</div></div>