• There is NO official Otland's Discord server and NO official Otland's server list. The Otland's Staff does not manage any Discord server or server list. Moderators or administrator of any Discord server or server lists have NO connection to the Otland's Staff. Do not get scammed!

Linux GDB backtrace report - internalMoveCreature

Snavy

Bakasta
Senator
Joined
Apr 1, 2012
Messages
1,249
Solutions
71
Reaction score
621
Location
Hell
TFS 1.3 - master branch

I have noticed this odd crash when I ctrl+walk and get pushed over the edge of mountains ( there are literally no tiles after the stairs, not even the invisible 460 tile).

confirmed that by checking in RME.
35862

but I could still ctrl+walk a few SQMs after the Stairs (yellow ones) and (not always) but most of the time the server crashes. I installed GDB and tried reading the backtrace report but wasn't able to read much except for "internalMoveCreature" which I recall modifying in order to enable admins push players anywhere (or atleast I tried).


Bash:
Program terminated with signal SIGSEGV, Segmentation fault.
#0  0x000055c9d8c11381 in Game::internalMoveCreature(Creature&, Tile&, unsigned int) ()
[Current thread is 1 (Thread 0x7fd4e7616700 (LWP 4316))]
(gdb) bt
#0  0x000055c9d8c11381 in Game::internalMoveCreature(Creature&, Tile&, unsigned int) ()
#1  0x000055c9d8c11364 in Game::internalMoveCreature(Creature*, Direction, unsigned int) ()
#2  0x000055c9d8c3d402 in Creature::onWalk() ()
#3  0x000055c9d8befa5c in Game::checkCreatureWalk(unsigned int) ()
#4  0x000055c9d8c3d815 in Creature::addEventWalk(bool) ()
#5  0x000055c9d8c3d74a in Creature::startAutoWalk(std::forward_list<Direction, std::allocator<Direction> > const&) ()
#6  0x000055c9d8be7d86 in Game::playerMove(unsigned int, Direction) ()
#7  0x000055c9d89e6eed in void std::__invoke_impl<void, void (Game::* const&)(unsigned int, Direction), Game*&, unsigned int&, Direction&>(std::__invoke_memfun_deref, void (Game::* const&)(unsigned int, Direction), Game*&, unsigned int&, Direction&)
    ()
#8  0x000055c9d89e5ad8 in std::result_of<void (Game::* const&(Game*&, unsigned int&, Direction&))(unsigned int, Direction)>::type std::__invoke<void (Game::* const&)(unsigned int, Direction), Game*&, unsigned int&, Direction&>(void (Game::* const&)(unsigned int, Direction), Game*&, unsigned int&, Direction&) ()
#9  0x000055c9d89e4484 in decltype (__invoke((*this)._M_pmf, (forward<Game*&>)({parm#1}), (forward<unsigned int&>)({parm#1}), (forward<Direction&>)({parm#1}))) std::_Mem_fn_base<void (Game::*)(unsigned int, Direction), true>::operator()<Game*&, unsigned int&, Direction&>(Game*&, unsigned int&, Direction&) const ()
#10 0x000055c9d89e09a0 in void std::_Bind<std::_Mem_fn<void (Game::*)(unsigned int, Direction)> (Game*, unsigned int, Direction)>::__call<void, , 0ul, 1ul, 2ul>(std::tuple<>&&, std::_Index_tuple<0ul, 1ul, 2ul>) ()
#11 0x000055c9d8a14a84 in void std::_Bind<std::_Mem_fn<void (Game::*)(unsigned int, Direction)> (Game*, unsigned int, Direction)>::operator()<, void>() ()
#12 0x000055c9d8a09e8a in std::_Function_handler<void (), std::_Bind<std::_Mem_fn<void (Game::*)(unsigned int, Direction)> (Game*, unsigned int, Direction)> >::_M_invoke(std::_Any_data const&) ()
#13 0x000055c9d89a77ee in std::function<void ()>::operator()() const ()
#14 0x000055c9d89a72ec in Task::operator()() ()
#15 0x000055c9d89a757b in Dispatcher::threadMain() ()
#16 0x000055c9d8a6554e in void std::__invoke_impl<void, void (Dispatcher::* const&)(), Dispatcher*>(std::__invoke_memfun_deref, void (Dispatcher::* const&)(), Dispatcher*&&) ()
#17 0x000055c9d8a65193 in std::result_of<void (Dispatcher::* const&(Dispatcher*&&))()>::type std::__invoke<void (Dispatcher::* const&)(), Dispatcher*>(void (Dispatcher::* const&)(), Dispatcher*&&) ()
#18 0x000055c9d8a64f82 in decltype (__invoke((*this)._M_pmf, (forward<Dispatcher*>)({parm#1}))) std::_Mem_fn_base<void (Dispatcher::*)(), true>::operator()<Dispatcher*>(Dispatcher*&&) const ()
#19 0x000055c9d8a64bcd in void std::_Bind_simple<std::_Mem_fn<void (Dispatcher::*)()> (Dispatcher*)>::_M_invoke<0ul>(std::_Index_tuple<0ul>) ()
#20 0x000055c9d8a6470d in std::_Bind_simple<std::_Mem_fn<void (Dispatcher::*)()> (Dispatcher*)>::operator()() ()
#21 0x000055c9d8a642a2 in std::thread::_State_impl<std::_Bind_simple<std::_Mem_fn<void (Dispatcher::*)()----------T--------Ty---Ty---Type---Ty-----Type---Type ----Type ---Ty---Type---Ty--------------------Type <return> to continue, or q <return> to quit---

The modification I made was from THIS Thread.

added this in Game::playerMoveCreature:
35863



I am suspecting that might be the cause of crash.


C++:
ReturnValue Game::internalMoveCreature(Creature* creature, Direction direction, uint32_t flags /*= 0*/)
{
    creature->setLastPosition(creature->getPosition());
    const Position& currentPos = creature->getPosition();
    Position destPos = getNextPosition(direction, currentPos);
    Player* player = creature->getPlayer();

    bool diagonalMovement = (direction & DIRECTION_DIAGONAL_MASK) != 0;
    if (player && !diagonalMovement) {
        //try go up
        if (currentPos.z != 8 && creature->getTile()->hasHeight(3)) {
            Tile* tmpTile = map.getTile(currentPos.x, currentPos.y, currentPos.getZ() - 1);
            if (tmpTile == nullptr || (tmpTile->getGround() == nullptr && !tmpTile->hasFlag(TILESTATE_BLOCKSOLID))) {
                tmpTile = map.getTile(destPos.x, destPos.y, destPos.getZ() - 1);
                if (tmpTile && tmpTile->getGround() && !tmpTile->hasFlag(TILESTATE_BLOCKSOLID)) {
                    flags |= FLAG_IGNOREBLOCKITEM | FLAG_IGNOREBLOCKCREATURE;

                    if (!tmpTile->hasFlag(TILESTATE_FLOORCHANGE)) {
                        player->setDirection(direction);
                        destPos.z--;
                    }
                }
            }
        }

        //try go down
        if (currentPos.z != 7 && currentPos.z == destPos.z) {
            Tile* tmpTile = map.getTile(destPos.x, destPos.y, destPos.z);
            if (tmpTile == nullptr || (tmpTile->getGround() == nullptr && !tmpTile->hasFlag(TILESTATE_BLOCKSOLID))) {
                tmpTile = map.getTile(destPos.x, destPos.y, destPos.z + 1);
                if (tmpTile && tmpTile->hasHeight(3)) {
                    flags |= FLAG_IGNOREBLOCKITEM | FLAG_IGNOREBLOCKCREATURE;
                    player->setDirection(direction);
                    destPos.z++;
                }
            }
        }
    }

    Tile* toTile = map.getTile(destPos);
    if (!toTile && !player->isAccessPlayer()) {
        return RETURNVALUE_NOTPOSSIBLE;
    }
    return internalMoveCreature(*creature, *toTile, flags);
}

ReturnValue Game::internalMoveCreature(Creature& creature, Tile& toTile, uint32_t flags /*= 0*/)
{
    //check if we can move the creature to the destination
    ReturnValue ret = toTile.queryAdd(0, creature, 1, flags);
    if (ret != RETURNVALUE_NOERROR) {
        std::cout << "queryAdd returned Error ... " << std::endl;
        return ret;
    }

    map.moveCreature(creature, toTile);
    if (creature.getParent() != &toTile) {
        return RETURNVALUE_NOERROR;
    }

    int32_t index = 0;
    Item* toItem = nullptr;
    Tile* subCylinder = nullptr;
    Tile* toCylinder = &toTile;
    Tile* fromCylinder = nullptr;
    uint32_t n = 0;

    while ((subCylinder = toCylinder->queryDestination(index, creature, &toItem, flags)) != toCylinder) {
        map.moveCreature(creature, *subCylinder);

        if (creature.getParent() != subCylinder) {
            //could happen if a script move the creature
            fromCylinder = nullptr;
            break;
        }

        fromCylinder = toCylinder;
        toCylinder = subCylinder;
        flags = 0;

        //to prevent infinite loop
        if (++n >= MAP_MAX_LAYERS) {
            break;
        }
    }

    if (fromCylinder) {
        const Position& fromPosition = fromCylinder->getPosition();
        const Position& toPosition = toCylinder->getPosition();
        if (fromPosition.z != toPosition.z && (fromPosition.x != toPosition.x || fromPosition.y != toPosition.y)) {
            Direction dir = getDirectionTo(fromPosition, toPosition);
            if ((dir & DIRECTION_DIAGONAL_MASK) == 0) {
                internalCreatureTurn(&creature, dir);
            }
        }
    }

    return RETURNVALUE_NOERROR;
}
 
Last edited:
change
Code:
flags |=
for
Code:
flags =

remove this |

although I doubt that it is the real problem, leave doubts eliminating the code.
I'm sure it's some of your modifications.

Why blame my code, if you have also modified those functions?

First make sure of what you say.

the trail of errors also shows walking functions, and my code has nothing to do with walking, it's just a simple flag.
 
Last edited:
change
Code:
flags |=
for
Code:
flags =

remove this |

although I doubt that it is the real problem, leave doubts eliminating the code.
I'm sure it's some of your modifications.

Why blame my code, if you have also modified those functions?

First make sure of what you say.

the trail of errors also shows walking functions, and my code has nothing to do with walking, it's just a simple flag.

:D calm down. I tested and that was not the issue. So I probably screwed something up.

the crash happens when I walk on those "non-existing" tiles.
I remember adding this log in internalMoveCreature (2nd function which takes references as parameters)
C++:
//check if we can move the creature to the destination
ReturnValue ret = toTile.queryAdd(0, creature, 1, flags);
if (ret != RETURNVALUE_NOERROR) {
    std::cout << "queryAdd returned Error ... " << std::endl;
    return ret;
}

and the crash happens randomly while trying to walk ( + getting those queryAdd errors )
35864
 
Code:
if (!toTile && !player->isAccessPlayer()) {
        return RETURNVALUE_NOTPOSSIBLE;
    }
So a bit of lecturing: if creature is not player you will always get crash at this point + if player have access it'll pass to the 2nd function with tile not existing = crash at queryadd
 
Back
Top