otland / forgottenserver

A free and open-source MMORPG server emulator written in C++
https://otland.net
GNU General Public License v2.0
1.59k stars 1.06k forks source link

[Bug]: Crash when monster spawns #4786

Closed ArturKnopik closed 2 weeks ago

ArturKnopik commented 1 month ago

By submitting this bug issue, you agree to the following.

Does this bug crash tfs?

yes

Server Version

1.7 (Master)

Operation System

all (listed below)

OS Description

No response

Bug description

Server crash when creature spawns

Possible Pull Requests which are to blame

No response

Steps to reproduce

  1. use this map world.zip
  2. use this monsters file monsters.zip 3 run server 4 login to normal character or god with summon to force monsters to attacks
  3. go to location {x = 116, y = 126, z = 7}
  4. start killing monsters, let monsters create poison fields(im not sourec if it's source of problem)
  5. crash (in few random places)

Actual Behavior

Crash

Expected Behavior

No crash

Backtrace

>   theforgottenserver-x64.exe!Tile::queryAdd(int __formal=0, const Thing & thing={...}, unsigned int __formal=1, unsigned int flags=48, Creature * __formal=0x0000000000000000) Line 508   C++
    theforgottenserver-x64.exe!Creature::updateTileCache(const Tile * tile=0x0000022c74846e40, int dx=3, int dy=3) Line 352 C++
    theforgottenserver-x64.exe!Creature::updateTileCache(const Tile * tile=0x0000022c74846e40, const Position & pos={...}) Line 365 C++
    theforgottenserver-x64.exe!Creature::updateMapCache() Line 345  C++
    theforgottenserver-x64.exe!Creature::onCreatureAppear(Creature * creature=0x0000022c73b46610, bool isLogin=true) Line 437   C++
    theforgottenserver-x64.exe!Monster::onCreatureAppear(Creature * creature=0x0000022c73b46610, bool isLogin=true) Line 116    C++
    theforgottenserver-x64.exe!Game::placeCreature(Creature * creature=0x0000022c73b46610, const Position & pos={...}, bool extendedPos=false, bool forced=true, MagicEffectClasses magicEffect=CONST_ME_TELEPORT) Line 528 C++
    theforgottenserver-x64.exe!Spawn::spawnMonster(unsigned int spawnId=1, MonsterType * mType=0x0000022c6a67d338, const Position & pos={...}, Direction dir=DIRECTION_SOUTH, bool startup=false) Line 331  C++
    theforgottenserver-x64.exe!Spawn::spawnMonster::__l2::<lambda_1>::operator()(bool roll=false) Line 289  C++
    theforgottenserver-x64.exe!Spawn::spawnMonster(unsigned int spawnId=1, spawnBlock_t sb={...}, bool startup=false) Line 302  C++
    theforgottenserver-x64.exe!Spawn::checkSpawn() Line 372 C++
    theforgottenserver-x64.exe!Spawn::startSpawnCheck::__l5::<lambda_1>::operator()() Line 246  C++
    [External Code] 
    theforgottenserver-x64.exe!Task::operator()() Line 23   C++
    theforgottenserver-x64.exe!Dispatcher::threadMain() Line 39 C++
    [External Code]

Additional info

ReturnValue Tile::queryAdd(int32_t, const Thing& thing, uint32_t, uint32_t flags, Creature*) const

Document   | Name | Value | Type -- | -- | -- | -- ◢ | tileCreature | 0x0000022c73b47b50 {position={x=56797 y=56797 z=221 'Ý' } damageMap={ size=15987178197214944733 } summons=...} | Creature *   | Thing | |     | ▶ __vfptr | 0xdddddddddddddddd {???, ???, ???, ???, ???, ???, ???, ???, ???, ???, ???, ???, ???, ???, ???, ???, ...} | void * *   | ▶ position | {x=56797 y=56797 z=221 'Ý' } | Position   | ▶ damageMap | { size=15987178197214944733 } | std::map,std::allocator>>   | ▶ summons | { size=15987178197214944733 } | std::list>   | ▶ eventsList | { size=15987178197214944733 } | std::list>   | ▶ conditions | { size=15987178197214944733 } | std::list>   | ▶ creatureIcons | { size=15987178197214944733 } | std::unordered_map,std::equal_to,std::allocator>>   | ▶ listWalkDir | { size=0 } | std::vector>   | ▶ tile | 0xdddddddddddddddd {ground=??? tilePos={x=??? y=??? z=??? } flags=??? } | Tile *   | ▶ attackedCreature | 0xdddddddddddddddd {position={x=??? y=??? z=??? } damageMap={ size=??? } summons={ size=??? } ...} | Creature *   | ▶ master | 0xdddddddddddddddd {position={x=??? y=??? z=??? } damageMap={ size=??? } summons={ size=??? } ...} | Creature *   | ▶ followCreature | 0xdddddddddddddddd {position={x=??? y=??? z=??? } damageMap={ size=??? } summons={ size=??? } ...} | Creature *   | lastStep | 15987178197214944733 | unsigned __int64   | referenceCounter | 3722304989 | unsigned int   | id | 3722304989 | unsigned int   | scriptEventsBitField | 3722304989 | unsigned int   | eventWalk | 3722304989 | unsigned int   | walkUpdateTicks | 3722304989 | unsigned int   | lastHitCreatureId | 3722304989 | unsigned int   | blockCount | 3722304989 | unsigned int   | blockTicks | 3722304989 | unsigned int   | lastStepCost | 3722304989 | unsigned int   | baseSpeed | 3722304989 | unsigned int   | varSpeed | -572662307 | int   | health | -572662307 | int   | healthMax | -572662307 | int   | drunkenness | 221 'Ý' | unsigned char   | ▶ currentOutfit | {lookType=56797 lookTypeEx=56797 lookHead=221 'Ý' ...} | Outfit_t   | ▶ defaultOutfit | {lookType=56797 lookTypeEx=56797 lookHead=221 'Ý' ...} | Outfit_t   | currentMount | 56797 | unsigned short   | ▶ lastPosition | {x=56797 y=56797 z=221 'Ý' } | Position   | ▶ internalLight | {level=221 'Ý' color=221 'Ý' } | LightInfo   | direction | 221 'Ý' | Direction   | skull | 221 'Ý' | Skulls_t   | ▶ localMapCache | 0x0000022c73b47cc2 {0x0000022c73b47cc2 {true (221), true (221), true (221), true (221), true (221), ...}, ...} | bool[23][23]   | isInternalRemoved | true (221) | bool   | isMapLoaded | true (221) | bool   | isUpdatingPath | true (221) | bool   | creatureCheck | true (221) | bool   | inCheckCreaturesVector | true (221) | bool   | skillLoss | true (221) | bool   | lootDrop | true (221) | bool   | cancelNextWalk | true (221) | bool   | hasFollowPath | true (221) | bool   | forceUpdateFollowPath | true (221) | bool   | hiddenHealth | true (221) | bool   | canUseDefense | true (221) | bool   | movementBlocked | true (221) | bool   | ▶ storageMap | { size=15987178197214944733 } | std::map,std::allocator>>
ArturKnopik commented 1 month ago

crash in another place

    theforgottenserver-x64.exe!Tile::removeThing(Thing * thing=0x0000017250315860, unsigned int count=1) Line 1135  C++
    theforgottenserver-x64.exe!Tile::addThing(int __formal=-1, Thing * thing=0x0000017250316790) Line 938   C++
    theforgottenserver-x64.exe!Game::internalAddItem(Cylinder * toCylinder=0x00000172471ca040, Item * item=0x0000017250316750, int index=-1, unsigned int flags=0, bool test=false, unsigned int & remainderCount=0) Line 1368  C++
    theforgottenserver-x64.exe!Game::internalAddItem(Cylinder * toCylinder=0x00000172471ca040, Item * item=0x0000017250316750, int index=-1, unsigned int flags=0, bool test=false) Line 1297   C++
    theforgottenserver-x64.exe!Combat::combatTileEffects(const SpectatorVec & spectators={...}, Creature * caster=0x00000172447949a0, Tile * tile=0x00000172471ca040, const CombatParams & params={...}) Line 595   C++
    theforgottenserver-x64.exe!Combat::doCombat(Creature * caster=0x00000172447949a0, const Position & position={...}) Line 742 C++
    theforgottenserver-x64.exe!CombatSpell::castSpell(Creature * creature=0x00000172447949a0, Creature * target=0x0000017244794ef0) Line 315    C++
    theforgottenserver-x64.exe!Monster::doAttacking(unsigned int interval=1000) Line 818    C++
    theforgottenserver-x64.exe!Creature::onAttacking(unsigned int interval=1000) Line 177   C++
>   theforgottenserver-x64.exe!Game::checkCreatures(unsigned __int64 index=3) Line 3863 C++
    theforgottenserver-x64.exe!Game::checkCreatures::__l2::<lambda_1>::operator()() Line 3853   C++
    [External Code] 
    theforgottenserver-x64.exe!Task::operator()() Line 23   C++
    theforgottenserver-x64.exe!Dispatcher::threadMain() Line 39 C++
    [External Code] 
>   theforgottenserver-x64.exe!Monster::addFriend(Creature * creature=0x00000213d8c02480) Line 310  C++
    theforgottenserver-x64.exe!Monster::onCreatureFound(Creature * creature=0x00000213d8c02480, bool pushFront=false) Line 410  C++
    theforgottenserver-x64.exe!Monster::updateTargetList() Line 376 C++
    theforgottenserver-x64.exe!Monster::onCreatureAppear(Creature * creature=0x00000213d8c02480, bool isLogin=true) Line 148    C++
    theforgottenserver-x64.exe!Game::placeCreature(Creature * creature=0x00000213d8c02480, const Position & pos={...}, bool extendedPos=false, bool forced=false, MagicEffectClasses magicEffect=CONST_ME_TELEPORT) Line 528    C++
    theforgottenserver-x64.exe!Monster::onThinkDefense(unsigned int interval=1000) Line 988 C++
    theforgottenserver-x64.exe!Monster::onThink(unsigned int interval=1000) Line 785    C++
    theforgottenserver-x64.exe!Game::checkCreatures(unsigned __int64 index=1) Line 3862 C++
    theforgottenserver-x64.exe!Game::checkCreatures::__l2::<lambda_1>::operator()() Line 3853   C++
    [External Code] 
    theforgottenserver-x64.exe!Task::operator()() Line 23   C++
    theforgottenserver-x64.exe!Dispatcher::threadMain() Line 39 C++
    [External Code] 

this one fail on
void Monster::addFriend(Creature* creature)
{
    assert(creature != this); <<HERE
    auto result = friendList.insert(creature);
    if (result.second) {
        creature->incrementReferenceCounter();
    }
}
ArturKnopik commented 1 month ago

https://github.com/otland/forgottenserver/blob/416df1912872d406e2cef4ef2ff57f9373cac7bf/src/game.cpp#L4504

if (target->getMaster()) {
    removeCreature(target);
    return true;
}

adding this code there fix issue but im not sure if it's good place for fix...

it's looks like after killing master and summon in same time leaves some trashes(invalid pointer to creature)

nekiro commented 2 weeks ago

Can you check if this pr #4803 resolves these crashes?

ArturKnopik commented 2 weeks ago

Tested for a while (10min) and no crash, before this fix it's take max 3min to get crash.

nekiro commented 2 weeks ago

Tested for a while (10min) and no crash, before this fix it's take max 3min to get crash.

thanks!