Menu

#1887 Hang when leaving SI dream world

Release Block
closed-fixed
None
9
2016-05-14
2014-10-21
No

Reported at http://exult.sourceforge.net/forum/read.php?f=1&i=949028&t=949028 .

Exult hangs when leaving the SI dream world.

The immediate cause is Actor::remove() calling unready usecode that already removes the item from the Actor. The following Container_game_object::remove(obj); call then assumes the object is still in the inventory, and continues to corrupt the world state. (We should add asserts to check for this.)

The usecode script running at the time is apparently the tournament script that returns items after returning from the dream world. At some point the black sword gets unequipped from an automaton (unclear why; maybe used as temp. storage), and this triggers the crash above.

As an aside, while this usecode is running, we add the black sword to the last_created stack twice. The second push gets intercepted because we don't allow this, and this causes additional last_created stack problems, on top of the crash above. (Unsure if this is a problem in itself or not.)

We may have to delay calling the unequip script for the black sword in SI (since it is significantly more complex than most unequip scripts), or maybe we shouldn't be calling unequip scripts at all when they're called from usecode. This needs testing in the original engine.

1 Attachments

Discussion

  • Dominik Reichardt

    • Group: Crash --> Release Block
    • Priority: 5 --> 9
     
  • Malignant Manor

    Malignant Manor - 2016-02-07
    • Attachments has changed:

    Diff:

    --- old
    +++ new
    @@ -0,0 +1 @@
    +bug 1887 saves.7z (591.6 kB; application/octet-stream)
    
     
  • Malignant Manor

    Malignant Manor - 2016-02-07

    Original and Exult saves before swamp and at fire in dreamland.

     
  • Phillip T. George

    Trying to take a look at this one. Very hairy though as far as tracking all of the classes/objects that do various remove functions and in some cases call multiple times.

    Here's a sample stack trace while exiting SI dream world thru death...was just watching for Actor::remove.

      * frame #0: 0x00000001000191f4 exult`Actor::remove(this=0x000000010ab100b0, obj=0x0000000100bad660) + 20 at actors.cc:3371
        frame #1: 0x0000000100490cb2 exult`Ireg_game_object::remove_this(this=0x0000000100bad660, nodel=1) + 98 at iregobjs.cc:95
        frame #2: 0x0000000100488315 exult`Container_game_object::remove_this(this=0x0000000100bad660, nodel=1) + 69 at contain.cc:718
        frame #3: 0x00000001003ab81c exult`Usecode_internal::UI_set_last_created(this=0x00000001040a6400, num_parms=1, parms=0x00007fff5fbf30a0) + 1180 at intrinsics.cc:541
    
     

    Last edit: Phillip T. George 2016-05-06
  • Phillip T. George

    Validated that this has something to do with a specific item being unreadied or the unready usecode itself in this context. Does appear to be the black sword to me as well. If I use lldb to return from call_usecode when its being unreadied, then its able to continue on. I think I'll be able to figure this out eventually. Assigning myself.

    * thread #1: tid = 0x2338fe, 0x00000001003d2aea exult`Usecode_internal::call_usecode(this=0x0000000101081400, id=806, item=0x000000010b38a450, event=unreadied) + 26 at ucinternal.cc:2910, queue = 'com.apple.main-thread', stop reason = breakpoint 2.1
        frame #0: 0x00000001003d2aea exult`Usecode_internal::call_usecode(this=0x0000000101081400, id=806, item=0x000000010b38a450, event=unreadied) + 26 at ucinternal.cc:2910
       2907     Game_object *item,      // Item ref.
       2908     Usecode_events event
       2909 ) {
    -> 2910     conv->clear_answers();
       2911 
       2912     int ret;
       2913     if (call_function(id, event, item, true))
    
     

    Last edit: Phillip T. George 2016-05-06
  • Phillip T. George

    • assigned_to: Phillip T. George
     
  • Phillip T. George

    • status: open --> pending-fixed
     
  • Phillip T. George

    I believe I have this fixed. Actor::remove has a check to see if the Actor is dead...if it is dead, it will not run "call_readied_usecode" which unreadies equiped items. However, when dying in the SI dream world, the avatar is NOT showing as dead. Anyway, the fix was to check and see if a "died" usecode event running (only if playing SI) for the main actor. If I tried just checking for the NPC's death in queue, but that doesn't make sense as part of the problem seems to be the automation NPC unreadying the weapon during the SI dream world death. I tested to make sure this does not impact normal death, and it should not, since the "is_dead" flag is set anyway, that part of the code is not ran. Also checked SI training and it still works...so I think we're good. I'll let someone else verify and close this.

     

    Last edit: Phillip T. George 2016-05-09
  • Dominik Reichardt

    thanks for looking into it.

     
  • Malignant Manor

    Malignant Manor - 2016-05-13

    This fix works for me. I asked Marzo in irc, and he thinks the fix is fine.

    Marzo: The original had a hack for the black sword: its unready event was done by way of a script instead of directly
    This can be seen by opening a gump and removing the black sword from inventory: it only returns when you close the gump
    So the "correct" solution would be to add a special case for the black sword
    His fix is simpler; if it works, I have no problems with it

    Malignant_Manor: Do you foresee any issues?
    Marzo: No; but Exult is a complex enough system that it is impossible to be sure

     
  • Malignant Manor

    Malignant Manor - 2016-05-13
    • status: pending-fixed --> closed-fixed
     
  • Phillip T. George

    Great -- glad to hear.