• 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!

Solved Crash with Fir3elements 0.4 - Cast System (Log Provided)

vinera0ot

Banned User
Joined
Oct 11, 2019
Messages
48
Reaction score
16
Last edited:
Crash Information:
When 2 players close the cast in same time server crashes

@Fir3element - Any ideas what could be causing this?
@Gesior.pl - And already done this step: Merge pull request #1 from gesior/cast_system_crash_fix · Fir3element/3777@29eb7a6 (https://github.com/Fir3element/3777/commit/29eb7a67e6994950687967f5afb69c39b04dd622)
and still server crashes


C++:
bool getCastingState() const {return cast.isCasting;};
        virtual const std::string& getCastingPassword() const {return cast.password;};

        PlayerCast getCast() {return cast;}

        void setCasting(bool c);
        void setCastPassword(std::string p) {cast.password = p;};

        void setCastDescription(std::string desc) {cast.description = desc;}

        virtual const std::string& getCastDescription() const {return cast.description;}

        void addCastViewer(ProtocolGame* pg)
        {
            cSpectators[nextSpectator] = pg;
            nextSpectator++;

            std::stringstream ss;
            ss << "Viewer " << cast.curId;
            pg->viewerName = ss.str().c_str();
            cast.curId++;
        }

        void removeCastViewer(uint32_t id) {cSpectators.erase(id);}

        uint32_t getCastIpByName(std::string n)
        {
            for(AutoList<ProtocolGame>::iterator it = cSpectators.begin(); it != cSpectators.end(); ++it)
            {
                if(it->second->getViewerName() == n && it->second->getPlayer() == this)
                    return it->second->getIP();
            }
            return false;
        }

        uint32_t getCastViewerCount()
        {
            uint32_t count = 0;
            for(AutoList<ProtocolGame>::iterator it = cSpectators.begin(); it != cSpectators.end(); ++it)
                    if(it->second->getPlayer() == this)
                        count++;

            return count;
        }

        void kickCastViewers()
        {
            AutoList<ProtocolGame>::iterator it = cSpectators.begin();
            while (it != cSpectators.end()) {
                if (it->second->getPlayer() == this) {
                    it->second->disconnect();
                    it->second->unRef();
                    it = cSpectators.erase(it);
                } else {
                    ++it;
                }
            }
            cast = PlayerCast();
        }

        void kickCastViewerByName(std::string n)
        {
            for(AutoList<ProtocolGame>::iterator it = cSpectators.begin(); it != cSpectators.end(); ++it) if(it->second->getPlayer() == this)
                if(it->second->getViewerName() == n && it->second->getPlayer() == this)
                {
                    it->second->disconnect();
                    it->second->unRef();
                    removeCastViewer(it->first);
                    return;
                }
        }

C++:
bool ProtocolGame::logout(bool displayEffect, bool forceLogout)
{
    //dispatcher thread
     if(!player)
        return false;
     
    if(getIsCast() && !player->isAccountManager())
    {
        PlayerCast pc = player->getCast();
        for(AutoList<ProtocolGame>::iterator it = Player::cSpectators.begin(); it != Player::cSpectators.end(); ++it)
            if(it->second == this)
                if(Connection_ptr connection = it->second->getConnection())
                {
                    PrivateChatChannel* channel = g_chat.getPrivateChannel(player);
                    if(channel) {
                        channel->talk("", SPEAK_CHANNEL_RA, (getViewerName() + " has left the cast."));
                    }

                    connection->close();
                    player->removeCastViewer(it->first);
                    return false;
                }
        return false;
    }

    if(!player->isRemoved())
    {
        if(!forceLogout)
        {
            if(!IOLoginData::getInstance()->hasCustomFlag(player->getAccount(), PlayerCustomFlag_CanLogoutAnytime))
            {
                if(player->getTile()->hasFlag(TILESTATE_NOLOGOUT))
                {
                    player->sendCancelMessage(RET_YOUCANNOTLOGOUTHERE);
                    return false;
                }

                if(player->getZone() != ZONE_PROTECTION && player->hasCondition(CONDITION_INFIGHT))
                {
                    player->sendCancelMessage(RET_YOUMAYNOTLOGOUTDURINGAFIGHT);
                    return false;
                }

                if(!g_creatureEvents->playerLogout(player, false)) //let the script handle the error message
                    return false;
            }
            else
                g_creatureEvents->playerLogout(player, true);
        }
        else if(!g_creatureEvents->playerLogout(player, true))
            return false;

        if(displayEffect && !player->isGhost())
            g_game.addMagicEffect(player->getPosition(), MAGIC_EFFECT_POFF);
    }

    player->kickCastViewers();

    if(Connection_ptr connection = getConnection())
        connection->close();

    if(player->isRemoved())
        return true;

    return g_game.removeCreature(player);
}

OS: Ubuntu 18:04 LTS

Regards and as always, thank you for any help in advance!
How much memory does your VPS have, and how big is your map?
 
Compile in Debug mode, run in Visual Studio and go up in call stack to check what’s the cause of the crash. Put some breakpoints and try once again and try to find cause.
 
Hi @Gesior.pl , how are you?
Reviving this thread, I was testing my server on Ubuntu 22.04 and came across a new crash episode on 3777 sources. I believe it’s related to the cast.

This time, I generated the log with gdb, and the bt full returned this output:
C++:
#1  0x0000586957c6ca85 in Chat::removeUserFromAllChannels(Player*) ()
No symbol table info available.
#2  0x0000586957e0f34f in Player::onCreatureDisappear(Creature const*, bool) ()
No symbol table info available.
#3  0x0000586957cef7ba in Game::removeCreature(Creature*, bool) ()
No symbol table info available.
#4  0x0000586957df78f9 in Player::onThink(unsigned int) ()
No symbol table info available.
#5  0x0000586957cf8768 in Game::checkCreatures() ()
No symbol table info available.
#6  0x0000586957cd3efb in Dispatcher::dispatcherThread(void*) ()

Do you have any idea what might be causing the problem?
This crash does not occur on Ubuntu 16.04.

Tks, man!
 
Do you have any idea what might be causing the problem?
This crash does not occur on Ubuntu 16.04.
Problem and fix: TFS 0.X - Crash: ChatChannel removeUser (https://otland.net/threads/crash-chatchannel-removeuser.277824/#post-2678114)
Other version of fix (first version is better, but does not compile on Windows as I remember): TFS 0.X - Crash: ChatChannel removeUser (https://otland.net/threads/crash-chatchannel-removeuser.277824/#post-2684101)

It did not occur on Ubuntu 16.04, because old C++ compiler generated less optimized code and bugged C++ code did not crash engine. With newer Linux version you get newer version of g++ compiler, which optimize more things during compilation.
 
Problem and fix: TFS 0.X - Crash: ChatChannel removeUser (https://otland.net/threads/crash-chatchannel-removeuser.277824/#post-2678114)
Other version of fix (first version is better, but does not compile on Windows as I remember): TFS 0.X - Crash: ChatChannel removeUser (https://otland.net/threads/crash-chatchannel-removeuser.277824/#post-2684101)

It did not occur on Ubuntu 16.04, because old C++ compiler generated less optimized code and bugged C++ code did not crash engine. With newer Linux version you get newer version of g++ compiler, which optimize more things during compilation.
Hey Gesior, first of all, thank you guy!
You are always very helpful <3.

I implemented the change that was suggested by adding this code in the chat.cpp:
C++:
    PrivateChannelMap::iterator it = m_privateChannels.begin();
    while(it != m_privateChannels.end())
    {
        it->second->removeUser(player);
        if(it->second->getOwner() == player->getGUID())
        {
            it->second->closeChannel();
            it = m_privateChannels.erase(it);
        }
        else
        {
            ++it;
        }
    }
The crash stopped happening in my testes. However, a new bug occurred now. I opened a cast, entered as a spectator, and then logged out (in spectator client). The client of the character who opened the cast started sending duplicate messages in the default channel (for example, if I type "hello" in default, it shows "hello" twice), and then the sprites all got messed up :O

Do you think this bug is related to this possible change?
I’ve never seen this before.

Many thanks!
Post automatically merged:

EDIT:
I reverted the change in the source (where the crash bug was) and managed to make the same bug with the messed up sprites and texts occur. The strange thing is that it happens with both: the spectator and the player who opened the cast. So, it has nothing to do with the fix you just helped me with.

I think the cast system from rev 3777 is the one that's actually bugged in newer ubuntu versions =(
Thanks for your attention, Gesior <3
 
Last edited:
Back
Top