<div dir="ltr"><div dir="ltr"><div dir="ltr"><div dir="ltr">Hi Nicolas,<br></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Sun, Dec 29, 2019 at 10:01 AM Nicolas Cellier <<a href="mailto:nicolas.cellier.aka.nice@gmail.com">nicolas.cellier.aka.nice@gmail.com</a>> wrote:<br></div><blockquote class="gmail_quote" 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"> <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></blockquote><div><br></div><div>I'm with you.  As I understand it this is a standard "break things into triangles and then render the scan lines along the edges of the triangles" 3D graphics algorithm, but at that point my "expertise" is revealed to be as vacuous as it is.  I think its straight-forward to fix for someone who understands the algorithm.  If "the edge is not on top toggle its (back) fills" the algorithm is nilling rightEdge (presumably to abort rendering that triangle?), and presumably this happens very rarely, rarely enough that Andreas never noticed he hadn't;'t programmed in the right continuation.  SO the question for people who can understand the algorithm is what the correct continuation is.</div><div><br></div><div>BTW, we're talking about the b3dMainLoop routine in platforms/Cross/plugins/Squeak3D/b3dMain.c</div><div><br></div><div><br></div><div>Another question is did Andreas ever prototype this in Smalltalk or did he write the C directly? (I suspect the latter).  On the off chance that he did prototype it, and one have any inkling where the Smalltalk code exists?</div><div> </div><blockquote class="gmail_quote" 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"><div dir="ltr"><div></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" target="_blank">eliot.miranda@gmail.com</a>> a écrit :<br></div><blockquote class="gmail_quote" 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"> <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-width:1px;border-left-style:solid;border-left-color: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-width:1px;border-left-style:solid;border-left-color: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-width:1px;border-left-style:solid;border-left-color: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-width:1px;border-left-style:solid;border-left-color: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-width:1px;border-left-style:solid;border-left-color: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>
</blockquote></div><br clear="all"><div><br></div>-- <br><div dir="ltr" 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></div>