[Vm-dev] VM crash in the Squeak3D plugin

Eliot Miranda eliot.miranda at gmail.com
Sun Dec 29 19:14:09 UTC 2019


On Sun, Dec 29, 2019 at 10:51 AM Eliot Miranda <eliot.miranda at gmail.com>
wrote:

> Hi
>
> On Sun, Dec 29, 2019 at 10:03 AM Eliot Miranda <eliot.miranda at gmail.com>
> wrote:
>
>> Hi Nicolas,
>>
>> On Sat, Dec 28, 2019 at 2:24 PM Nicolas Cellier <
>> nicolas.cellier.aka.nice at gmail.com> wrote:
>>
>>>
>>> I forgot to say that I had an assert failure report:
>>>
>>> leftEdge && rightEdge 1398
>>>
>>> Looking around line 1398:
>>>
>>>                                         /*-- search for the next top
>>> edge which will be the right edge --*/
>>>                                         assert(aetStart < aetSize);
>>>                                         if(!fillList->firstFace)
>>>                                                 rightEdge =
>>> aetData[aetStart++]; /* If no current top fill just use the next edge */
>>>                                         else while(aetStart < aetSize) {
>>> /* Search for the next top edge in the AET */
>>>                                                 rightEdge =
>>> aetData[aetStart];
>>>                                                 /* If we have an
>>> intersection use the intersection edge */
>>>
>>> if(nextIntersection->xValue <= rightEdge->xValue) {
>>>                                                         rightEdge =
>>> nextIntersection;
>>>                                                         break;
>>>                                                 }
>>>                                                 aetStart++;
>>>                                                 /* Check if this edge is
>>> on top */
>>>
>>> assert(fillList->firstFace);
>>>                                                 {
>>>                                                         double xValue =
>>> rightEdge->xValue * B3D_FixedToFloat;
>>>                                                         B3DPrimitiveFace
>>> *topFace = fillList->firstFace;
>>>                                                         if(
>>> rightEdge->leftFace == topFace ||
>>>
>>> rightEdge->rightFace == topFace ||
>>>
>>> rightEdge->zValue < zValueAt(topFace, xValue, yValue))
>>>                                                                 break;
>>> /* rightEdge is on top */
>>>                                                 }
>>>                                                 /* If the edge is not on
>>> top toggle its (back) fills */
>>>
>>> b3dToggleBackFills(fillList, rightEdge, yValue, nextIntersection);
>>>                                                 rightEdge = NULL;
>>>                                         }
>>>                                         /*-- end of search for next top
>>> edge --*/
>>>
>>
>> So these lines (1390 to 1392 immediately above)
>>
>>                         /* If the edge is not on top toggle its (back)
>> fills */
>>                         b3dToggleBackFills(fillList, rightEdge, yValue,
>> nextIntersection);
>>                         rightEdge = NULL;
>>
>> are the key lines.  What is the meaning of "If the edge is not on top
>> toggle its (back) fills", and what is the continuation?  Clearly the
>> continuation should not be to continue after the if because that continues
>> into the code that indirects through the null pointer at line 1407:
>>
>>                     if(fillList->firstFace) {
>>                         /* Note: We fill *including* leftX and rightX */
>>                         int leftX = (leftEdge->xValue >>
>> B3D_FixedToIntShift) + 1;
>> >>                    int rightX = (rightEdge->xValue >>
>> B3D_FixedToIntShift);
>>                         B3DPrimitiveFace *topFace = fillList->firstFace;
>>
>> So, 3D graphics experts, what is going on here, and how should the
>> algorithm continue when "the edge is not on top toggle its (back) fills"?
>>
>>
>
> Changing my hacked in assert sequence to the following fixes the crash but
> I think causes the system to lock up (Stéphane using your WondwerlandPark
> game.  The old code crashes after 100 seconds of rotating the startup
> screen; this new code runs for about 5 minutes and then the VM appears to
> lock up)
>
> #if 1
>                     if (!rightEdge) {
>                         b3dCleanupFill(fillList);
>                         break;
>                     }
> #elif 1 /* This assert fails in rare cases; the fix is not understood. eem
> */
>                     assert(leftEdge && rightEdge);
> #else
>                     if(!leftEdge || !rightEdge)
>                         FAIL_UPDATING(B3D_NO_MORE_EDGES); // another
> segfault
>                         //FAIL_PAINTING(B3D_NO_MORE_EDGES); // blow up in
> allocating edges
> #endif
>
>
> as it does if the continuation is simply
>
>                     if (!rightEdge)
>                         break;
>
> So close, but no cigar...
>

I think I have it.  An old case of Stéphane's is still running after 10
minutes without locking up.  The continuation is

                    if (!rightEdge) {
                        aet->size = 0;
                        b3dCleanupFill(fillList);
                        break;
                    }

The break causes exit from the loop at 1352.  And the set->size = 0
assignment then causes exit from the enclosing loop at 1227 (the BEGIN
MAINLOOP loop).

I'm going to commit this.  Stéphane, sorry it has taken so long to get to
this.  As you can see neither Nicolas nor I understand the code to any
sufficient level.  We're going on very primitive understanding rather than
familiarity with the algorithm.  Anyway, hopefully this fix will stand the
test of time.


>
>
>>                                         /*-- Now do the drawing from
>>> leftEdge to rightEdge --*/
>>> #if 1 /* This assert fails in rare cases; the fix is not understood. eem
>>> */
>>>                                         assert(leftEdge && rightEdge);
>>> #else
>>>                                         if(!leftEdge || !rightEdge)
>>>
>>> FAIL_UPDATING(B3D_NO_MORE_EDGES); // another segfault
>>>
>>> //FAIL_PAINTING(B3D_NO_MORE_EDGES); // blow up in allocating edges
>>> #endif
>>>                                         if(fillList->firstFace) {
>>>                                                 /* Note: We fill
>>> *including* leftX and rightX */
>>>                                                 int leftX =
>>> (leftEdge->xValue >> B3D_FixedToIntShift) + 1;
>>>                                                 int rightX =
>>> (rightEdge->xValue >> B3D_FixedToIntShift);
>>>
>>> So I'm pretty sure that we went thru:
>>>
>>>                                                 /* If the edge is not on
>>> top toggle its (back) fills */
>>>
>>> b3dToggleBackFills(fillList, rightEdge, yValue, nextIntersection);
>>>                                                 rightEdge = NULL;
>>>
>>> if intention of #if 1... assert(...) was probably to debug the case of
>>> failure...
>>> But it was left in the release. Maybe it would be safer to replace with
>>> #ifdef DEBUG or something like that?
>>> Eliot?
>>>
>>> Le sam. 28 déc. 2019 à 23:04, Nicolas Cellier <
>>> nicolas.cellier.aka.nice at gmail.com> a écrit :
>>>
>>>> Running SqueakDebug.app in lldb, I get:
>>>>
>>>> Process 61332 stopped
>>>> * thread #1, queue = 'com.apple.main-thread', stop reason =
>>>> EXC_BAD_ACCESS (code=1, address=0x18)
>>>>     frame #0: 0x09f17c07 Squeak3D`b3dMainLoop(state=0x09f1928c,
>>>> stopReason=0) at b3dMain.c:1407:32
>>>>    1404 if(fillList->firstFace) {
>>>>    1405 /* Note: We fill *including* leftX and rightX */
>>>>    1406 int leftX = (leftEdge->xValue >> B3D_FixedToIntShift) + 1;
>>>> -> 1407 int rightX = (rightEdge->xValue >> B3D_FixedToIntShift);
>>>>    1408 B3DPrimitiveFace *topFace = fillList->firstFace;
>>>>    1409
>>>>    1410 if(leftX < 0) leftX = 0;
>>>> Target 0: (Squeak) stopped.
>>>> (lldb) print rightEdge
>>>> (B3DPrimitiveEdge *) $0 = 0x00000000
>>>> (lldb) print leftEdge
>>>> (B3DPrimitiveEdge *) $1 = 0x0617a49c
>>>> (lldb) bt
>>>> * thread #1, queue = 'com.apple.main-thread', stop reason =
>>>> EXC_BAD_ACCESS (code=1, address=0x18)
>>>>   * frame #0: 0x09f17c07 Squeak3D`b3dMainLoop(state=0x09f1928c,
>>>> stopReason=0) at b3dMain.c:1407:32
>>>>     frame #1: 0x09f0cb23 Squeak3D`b3dStartRasterizer at
>>>> Squeak3D.c:1704:12
>>>>     frame #2: 0x05d01398
>>>>     frame #3: 0x00002f52 Squeak`interpret at gcc3x-cointerp.c:2749:3
>>>>
>>>> So why rightEdge is a null pointer?
>>>> If you already examined the code, you may have an idea...
>>>>
>>>> Le sam. 28 déc. 2019 à 22:55, Nicolas Cellier <
>>>> nicolas.cellier.aka.nice at gmail.com> a écrit :
>>>>
>>>>> Hi Stephane,
>>>>> I confirm that I can reproduce the crash with an up-to-date VM (on
>>>>> OSX).
>>>>>
>>>>> Le sam. 28 déc. 2019 à 19:20, Stéphane Rollandin <
>>>>> lecteur at zogotounga.net> a écrit :
>>>>>
>>>>>>
>>>>>> Hello all,
>>>>>>
>>>>>> For my first post on this list, I would like to submit the bug that
>>>>>> prevents one of my game (this one:
>>>>>> http://www.zogotounga.net/comp/guardians.htm) to work reliably.
>>>>>>
>>>>>> I spent quite some time on this, and I ended up with a nice and
>>>>>> concise
>>>>>> way to crash the Squeak3D plugin. The image is available at:
>>>>>>
>>>>>> http://www.zogotounga.net/swap/crashlab3.zip
>>>>>>
>>>>>> Instructions to crash the VM are detailed therein.
>>>>>>
>>>>>> The 3D scene is very simple, there are only three objects. The crash
>>>>>> seems related to a race condition, because inserting a simple delay in
>>>>>> the code prevents it - this is detailed in the image itself.
>>>>>>
>>>>>> I have spent days studying the Smalltalk code, and could not see
>>>>>> anything wrong with what is sent to the plugin. It looks to my
>>>>>> uninformed eyes as a problem of shared memory, where one rasterizing
>>>>>> operation messes up with another happening in parallel (although no
>>>>>> processed is being forked on the Smalltalk side).
>>>>>>
>>>>>>
>>>>>> Stef
>>>>>>
>>>>>
>>
>> --
>> _,,,^..^,,,_
>> best, Eliot
>>
>
>
> --
> _,,,^..^,,,_
> best, Eliot
>


-- 
_,,,^..^,,,_
best, Eliot
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.squeakfoundation.org/pipermail/vm-dev/attachments/20191229/8c6cb3a0/attachment-0001.html>


More information about the Vm-dev mailing list