<div dir="ltr"><div>Thanks to Stephane, we have a reproducible case and might understand why/how this happens...</div><div>Unfortunately, I have no idea what the algorithm does, it would deserve some more documentation.</div><div>Is this a classical algorithm that can be found in litterature?<br></div></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">Le dim. 29 déc. 2019 à 18:50, Eliot Miranda <<a href="mailto:eliot.miranda@gmail.com">eliot.miranda@gmail.com</a>> a écrit :<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"> <div dir="ltr"><div dir="ltr"><div dir="ltr"><div dir="ltr"><div dir="ltr"><div dir="ltr"><div dir="ltr"><div dir="ltr"><div dir="ltr">Hi Nicolas, Hi Stéphane,</div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Sat, Dec 28, 2019 at 2:24 PM Nicolas Cellier <<a href="mailto:nicolas.cellier.aka.nice@gmail.com" target="_blank">nicolas.cellier.aka.nice@gmail.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"> <div dir="ltr"><div>I forgot to say that I had an assert failure report:</div><div><br></div><div>leftEdge && rightEdge 1398</div><div><br></div><div>Looking around line 1398: <br></div><div><br></div><div>                                        /*-- search for the next top edge which will be the right edge --*/<br>                                        assert(aetStart < aetSize);<br>                                        if(!fillList->firstFace)<br>                                                rightEdge = aetData[aetStart++]; /* If no current top fill just use the next edge */<br>                                        else while(aetStart < aetSize) { /* Search for the next top edge in the AET */<br>                                                rightEdge = aetData[aetStart];<br>                                                /* If we have an intersection use the intersection edge */<br>                                                if(nextIntersection->xValue <= rightEdge->xValue) {<br>                                                        rightEdge = nextIntersection;<br>                                                        break;<br>                                                }<br>                                                aetStart++;<br>                                                /* Check if this edge is on top */<br>                                                assert(fillList->firstFace);<br>                                                {<br>                                                        double xValue = rightEdge->xValue * B3D_FixedToFloat;<br>                                                        B3DPrimitiveFace *topFace = fillList->firstFace;<br>                                                        if( rightEdge->leftFace == topFace ||<br>                                                                rightEdge->rightFace == topFace ||<br>                                                                rightEdge->zValue < zValueAt(topFace, xValue, yValue))<br>                                                                break; /* rightEdge is on top */<br>                                                }<br>                                                /* If the edge is not on top toggle its (back) fills */<br>                                                b3dToggleBackFills(fillList, rightEdge, yValue, nextIntersection);<br>                                                rightEdge = NULL;<br>                                        }<br>                                        /*-- end of search for next top edge --*/<br><br>                                        /*-- Now do the drawing from leftEdge to rightEdge --*/<br>#if 1 /* This assert fails in rare cases; the fix is not understood. eem */<br>                                        assert(leftEdge && rightEdge);<br>#else<br>                                        if(!leftEdge || !rightEdge)<br>                                                FAIL_UPDATING(B3D_NO_MORE_EDGES); // another segfault<br>                                                //FAIL_PAINTING(B3D_NO_MORE_EDGES); // blow up in allocating edges<br>#endif<br>                                        if(fillList->firstFace) {<br>                                                /* Note: We fill *including* leftX and rightX */<br>                                                int leftX = (leftEdge->xValue >> B3D_FixedToIntShift) + 1;<br>                                                int rightX = (rightEdge->xValue >> B3D_FixedToIntShift);</div><div><br></div><div>So I'm pretty sure that we went thru:</div><div><br></div><div>                                                /* If the edge is not on top toggle its (back) fills */<br>                                                b3dToggleBackFills(fillList, rightEdge, yValue, nextIntersection);<br>                                                rightEdge = NULL;</div><div><br></div><div>if intention of #if 1... assert(...) was probably to debug the case of failure...</div><div>But it was left in the release. Maybe it would be safer to replace with #ifdef DEBUG or something like that?</div><div>Eliot?<br></div></div></blockquote><br>I remember now.<br><br>The original code read<br><br>-                                      assert(rightEdge);<br><br>and this din't catch the crash.  So I added the #else arm:<br><br>+                                       if(!leftEdge || !rightEdge)<br>+                                               FAIL_PAINTING(B3D_NO_MORE_EDGES); // blow up in allocating edges<br><br>which caused the system to fail not being able to allocate edges.  So I tried an alternative:<br><br>+                                       if(!leftEdge || !rightEdge)<br>+                                               FAIL_UPDATING(B3D_NO_MORE_EDGES); // another segfault<br><br>which caused segfaults.  So I added the stronger assert, and ifdefed out my two attempts at failing correctly in the #else arm.<br><br>+                                       assert(leftEdge && rightEdge);<br><br>So by all means strip the code back to the assert, but I think that the information that both of those attempts at remediation, FAIL_PAINTING(B3D_NO_MORE_EDGES); and FAIL_UPDATING(B3D_NO_MORE_EDGES);, failed and for different reasons might be useful to know.</div><br>The question is under what circumstances does the assert(leftEdge && rightEdge); fail?<div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div></div></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">Le sam. 28 déc. 2019 à 23:04, Nicolas Cellier <<a href="mailto:nicolas.cellier.aka.nice@gmail.com" target="_blank">nicolas.cellier.aka.nice@gmail.com</a>> a écrit :<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div>Running SqueakDebug.app in lldb, I get:</div><div><br></div><div>Process 61332 stopped<br>* thread #1, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=1, address=0x18)<br>    frame #0: 0x09f17c07 Squeak3D`b3dMainLoop(state=0x09f1928c, stopReason=0) at b3dMain.c:1407:32<br>   1404                                               if(fillList->firstFace) {<br>   1405                                                 /* Note: We fill *including* leftX and rightX */<br>   1406                                                     int leftX = (leftEdge->xValue >> B3D_FixedToIntShift) + 1;<br>-> 1407                                                 int rightX = (rightEdge->xValue >> B3D_FixedToIntShift);<br>   1408                                                    B3DPrimitiveFace *topFace = fillList->firstFace;<br>   1409  <br>   1410                                                     if(leftX < 0) leftX = 0;<br>Target 0: (Squeak) stopped.<br>(lldb) print rightEdge<br>(B3DPrimitiveEdge *) $0 = 0x00000000<br>(lldb) print leftEdge<br>(B3DPrimitiveEdge *) $1 = 0x0617a49c<br>(lldb) bt<br>* thread #1, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=1, address=0x18)<br>  * frame #0: 0x09f17c07 Squeak3D`b3dMainLoop(state=0x09f1928c, stopReason=0) at b3dMain.c:1407:32<br>    frame #1: 0x09f0cb23 Squeak3D`b3dStartRasterizer at Squeak3D.c:1704:12<br>    frame #2: 0x05d01398<br>    frame #3: 0x00002f52 Squeak`interpret at gcc3x-cointerp.c:2749:3</div><div><br></div><div>So why rightEdge is a null pointer?</div><div>If you already examined the code, you may have an idea...<br></div></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">Le sam. 28 déc. 2019 à 22:55, Nicolas Cellier <<a href="mailto:nicolas.cellier.aka.nice@gmail.com" target="_blank">nicolas.cellier.aka.nice@gmail.com</a>> a écrit :<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div>Hi Stephane,</div><div>I confirm that I can reproduce the crash with an up-to-date VM (on OSX).<br></div></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">Le sam. 28 déc. 2019 à 19:20, Stéphane Rollandin <<a href="mailto:lecteur@zogotounga.net" target="_blank">lecteur@zogotounga.net</a>> a écrit :<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"> <br>
Hello all,<br>
<br>
For my first post on this list, I would like to submit the bug that <br>
prevents one of my game (this one: <br>
<a href="http://www.zogotounga.net/comp/guardians.htm" rel="noreferrer" target="_blank">http://www.zogotounga.net/comp/guardians.htm</a>) to work reliably.<br>
<br>
I spent quite some time on this, and I ended up with a nice and concise <br>
way to crash the Squeak3D plugin. The image is available at:<br>
<br>
<a href="http://www.zogotounga.net/swap/crashlab3.zip" rel="noreferrer" target="_blank">http://www.zogotounga.net/swap/crashlab3.zip</a><br>
<br>
Instructions to crash the VM are detailed therein.<br>
<br>
The 3D scene is very simple, there are only three objects. The crash<br>
seems related to a race condition, because inserting a simple delay in<br>
the code prevents it - this is detailed in the image itself.<br>
<br>
I have spent days studying the Smalltalk code, and could not see<br>
anything wrong with what is sent to the plugin. It looks to my<br>
uninformed eyes as a problem of shared memory, where one rasterizing<br>
operation messes up with another happening in parallel (although no<br>
processed is being forked on the Smalltalk side).<br>
<br>
<br>
Stef<br>
</blockquote></div>
</blockquote></div>
</blockquote></div>
</blockquote></div><br clear="all"><div><br></div>-- <br><div dir="ltr"><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></div></div></div></div></div>
</blockquote></div>