Panel użytkownika
Nazwa użytkownika:
Hasło:
Nie masz jeszcze konta?

[LUA][C++] gdb problem z silnikiem gry

Ostatnio zmodyfikowano 2022-10-05 19:52
Autor Wiadomość
dunno
Temat założony przez niniejszego użytkownika
» 2022-10-03 19:15:05
Ok, dodałem i chyba w zbyt wielu miejscach dodałem bo lagowało serwer, ale już jest stabilnie. Tylko dalej nie wiem czy dodałem te locki w poprawnych miejscach. Jak to zrozumić ze np: w Game::creatureOnPrepareMagicAttack nie wymaga locka

C/C++
bool Game::creatureOnPrepareMagicAttack( Creature * creature, Position pos, const MagicEffectClass * me )
{
   
if( !me->offensive || me->isIndirect() || creatureOnPrepareAttack( creature, pos ) ) {
       
/*
   if(creature->access < ACCESS_PROTECT) {
    if(!((std::abs(creature->pos.x-centerpos.x) <= 8) && (std::abs(creature->pos.y-centerpos.y) <= 6) &&
     (creature->pos.z == centerpos.z)))
     return false;
   }
  */
       
       
Player * player = dynamic_cast < Player * >( creature );
       
if( player ) {
           
if( player->access < g_config.ACCESS_PROTECT ) {
               
if( player->exhaustedTicks >= 1000 && me->causeExhaustion( true ) ) {
                   
if( me->offensive ) {
                       
player->sendTextMessage( MSG_SMALLINFO, "You are exhausted.", player->pos, NM_ME_PUFF );
                       
player->exhaustedTicks += g_config.EXHAUSTED_ADD;
                   
}
                   
                   
return false;
               
}
               
else if( player->mana < me->manaCost ) {
                   
player->sendTextMessage( MSG_SMALLINFO, "You do not have enough mana.", player->pos, NM_ME_PUFF );
                   
return false;
               
}
               
else
                   
 player->mana -=( int64_t ) me->manaCost;
               
//player->manaspent += me->manaCost;
               
player->addManaSpent(( int64_t ) me->manaCost );
           
}
        }
       
       
return true;
   
}
   
   
return false;
}

a np. w creatureThrowRune
C/C++
bool Game::creatureThrowRune( Creature * creature, const Position & centerpos, const MagicEffectClass & me ) {
   
   
OTSYS_THREAD_LOCK_CLASS lockClass( gameLock, "Game::creatureThrowRune()" );
   
   
bool ret = false;
   
if( creature->pos.z != centerpos.z ) {
       
creature->sendCancel( "You need to be on the same floor." );
   
}
   
//else if(!map->canThrowItemTo(creature->pos, centerpos, false, true)) {
   
else if( map->canThrowObjectTo( creature->pos, centerpos, BLOCK_PROJECTILE ) != RET_NOERROR ) {
       
creature->sendCancel( "You cannot throw there." );
   
}
   
else
       
 ret = creatureMakeMagic( creature, centerpos, & me );
   
   
   
   
return ret;
}

juz wymaga locka.
P-179678
pekfos
» 2022-10-03 23:31:42
Jak to zrozumić ze np: w Game::creatureOnPrepareMagicAttack nie wymaga locka
Jedyne użycie creatureOnPrepareMagicAttack jest w creatureMakeMagic, gdzie lock już jest.

a np. w creatureThrowRune juz wymaga locka.
To że jest, nie znaczy że jest wymagany. Mógł być potrzebny w przeszłości, albo dodany bez powodu.

Tylko dalej nie wiem czy dodałem te locki w poprawnych miejscach.
A zidentyfikowałeś jakieś problemy, czy po prostu dodawałeś?
P-179679
dunno
Temat założony przez niniejszego użytkownika
» 2022-10-04 18:54:44
A zidentyfikowałeś jakieś problemy, czy po prostu dodawałeś?
Wiem, że nie robie tego poprawnie - po prostu dodawałem.

Gdy dodałem np. tu
C/C++
void Game::parseMove( Player * player, const Direction & dir )
{
   
/*
#ifdef DODATKOWE_LOCKI
 OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::parseMove()");
#endif //DODATKOWE_LOCKI*/
   
player->notAfk();
   
int64_t delay = player->getSleepTicks();
   
if( delay > 0 ) {
       
player->sleepProtocol( delay );
   
}
   
internalMovePlayer( player, dir );
}

bool Game::internalMovePlayer( Player * player, const Direction & dir )
{
   
/*#ifdef DODATKOWE_LOCKI
 OTSYS_THREAD_LOCK_CLASS lockClass(gameLock, "Game::internalMovePlayer()");
#endif //DODATKOWE_LOCKI*/
   
Position pos = player->pos;
   
bool diagonalMove = changePosByDir( dir, pos );
   
if( diagonalMove ) {
       
player->lastmove = OTSYS_TIME() + player->getStepDuration();
   
}
   
else
   
{
       
player->lastmove = OTSYS_TIME();
   
}
   
thingMove( player, player, pos.x, pos.y, pos.z, 1 );
   
return true;
}
co odpowiada za chodzenie gracza, to tak zawieszało gracza, ze w tych miejscach musiałem zakomentować.

ale już np. w tej modzie
C/C++
void Game::addBlood( Creature * attackedCreature, Position & bloodPos, bool dead )
{
   
#ifdef DODATKOWE_LOCKI
   
OTSYS_THREAD_LOCK_CLASS lockClass( gameLock, "Game::addBlood()" );
   
#endif  //DODATKOWE_LOCKI
   
if( attackedCreature->bloodsplash != 255 )
   
{
       
Player * attackedplayer = dynamic_cast < Player * >( attackedCreature );
       
Item * splash = Item::CreateItem( dead ? ITEM_POOL: ITEM_SPLASH, attackedCreature->bloodsplash );
       
addThing( NULL, bloodPos, splash );
       
startDecay( splash );
       
if( attackedplayer && dead )
           
 attackedplayer->onThingAppear( splash ); //just to make sure he watches his own blood ruining the floor ;D
       
       
updateTile( bloodPos );
   
}
}
zostawiłem locka (jak i w kilku innych).

W ogóle zastanawia mnie dlaczego w parseMove i internalMovePlayer nie moze byc locka bo zamula gracza, przecież i tu może się zdarzyć że "dwa fragmenty kodu będą wykonywały się jednocześnie" gdy nie ma locka.


Raczej to robie metodą prób i błędów. Wiem, że to prymitywne rozwiązywanie problemu, ale inaczej ciężko jest mi z tym sobie na ten moment poradzić. Gdy problem będzie się będzie powtarzał to skopiuje sobie core dumpa zeby mi sie nie nadpisal i wtedy wrzucę jakieś dodatkowe logi.
P-179680
pekfos
» 2022-10-05 18:59:13
tak zawieszało gracza, ze w tych miejscach musiałem zakomentować.
To nie jest bez kosztu wydajnościowego. Kompilujesz to z __DEBUG_CRITICALSECTION__? Te makro włącza logowanie każdego locka i sam mechanizm logowania nie jest bezpieczny. Dostęp do OTSYS_THREAD_LOCK_CLASS::loglist nie jest synchronizowany.

W ogóle zastanawia mnie dlaczego w parseMove i internalMovePlayer nie moze byc locka bo zamula gracza, przecież i tu może się zdarzyć że "dwa fragmenty kodu będą wykonywały się jednocześnie" gdy nie ma locka.
Nie mam w kodzie takich nazw, ale jakby faktycznie tak się mogło zdarzyć, to by znaczyło że jednak znalazłeś jakieś problemy.
P-179684
dunno
Temat założony przez niniejszego użytkownika
» 2022-10-05 19:52:05
To nie jest bez kosztu wydajnościowego. Kompilujesz to z __DEBUG_CRITICALSECTION__? Te makro włącza logowanie każdego locka i sam mechanizm logowania nie jest bezpieczny. Dostęp do OTSYS_THREAD_LOCK_CLASS::loglist nie jest synchronizowany.

Ostatnio próbowałem skompilować z -D__DEBUG_CRITICALSECTION__ ale sypneło mi wieloma błędami
In file included from database.h:5,
                 from actions.cpp:5:
otsystem.h:263:21: error: âlogBlockâ was not declared in this scope
  typedef std::list< logBlock > LogList;
                     ^~~~~~~~
otsystem.h:263:21: note: suggested alternative: âsigblockâ
  typedef std::list< logBlock > LogList;
                     ^~~~~~~~
                     sigblock
otsystem.h:263:30: error: template argument 1 is invalid
  typedef std::list< logBlock > LogList;
                              ^
otsystem.h:263:30: error: template argument 2 is invalid
otsystem.h: In static member function âstatic void OTSYS_THREAD_LOCK_CLASS::addL                                                                                        og(OTSYS_THREAD_LOCKVAR*, const char*, bool)â:
otsystem.h:242:5: error: âlogBlockâ was not declared in this scope
     logBlock lb;
     ^~~~~~~~
otsystem.h:242:5: note: suggested alternative: âsigblockâ
     logBlock lb;
     ^~~~~~~~
     sigblock
otsystem.h:243:3: error: âlbâ was not declared in this scope
   lb.mutexaddr = (unsigned long)(a);
   ^~
otsystem.h:247:17: error: âGetCurrentThreadIdâ was not declared in this scope
   lb.threadid = GetCurrentThreadId();
                 ^~~~~~~~~~~~~~~~~~
otsystem.h:247:17: note: suggested alternative: âxmlGetThreadIdâ
   lb.threadid = GetCurrentThreadId();
                 ^~~~~~~~~~~~~~~~~~
                 xmlGetThreadId
otsystem.h:249:36: error: request for member âpush_backâ in âOTSYS_THREAD_LOCK_C                                                                                        LASS::loglistâ, which is of non-class type âOTSYS_THREAD_LOCK_CLASS::LogListâ {a                                                                                        ka âintâ}
   OTSYS_THREAD_LOCK_CLASS::loglist.push_back(lb);
                                    ^~~~~~~~~
otsystem.h:251:39: error: request for member âsizeâ in âOTSYS_THREAD_LOCK_CLASS:                                                                                        :loglistâ, which is of non-class type âOTSYS_THREAD_LOCK_CLASS::LogListâ {aka âi                                                                                        ntâ}
   if(OTSYS_THREAD_LOCK_CLASS::loglist.size() > 1000) {
                                       ^~~~
otsystem.h:252:37: error: request for member âpop_frontâ in âOTSYS_THREAD_LOCK_C                                                                                        LASS::loglistâ, which is of non-class type âOTSYS_THREAD_LOCK_CLASS::LogListâ {a                                                                                        ka âintâ}
    OTSYS_THREAD_LOCK_CLASS::loglist.pop_front();
                                     ^~~~~~~~~

Więc kompiluje bez tego.
na ten moment uruchamiam bez logowania crashy przez gdb tj;
ENDFLAGS=-Werror -O2 -Winvalid-pch -include "preheaders.h"

wtedy gracze nie narzekają, ze ich zacina

a jak pojawiają sie problemy to kompiluje z gdb
ENDFLAGS=-Werror -g -ggdb -Winvalid-pch -include "preheaders.h"



Nie mam w kodzie takich nazw, ale jakby faktycznie tak się mogło zdarzyć, to by znaczyło że jednak znalazłeś jakieś problemy.
Niby tak, ale nie jestem przekonany że to ma jakikolwiek wpływ, ponieważ właściwie na zmianę korzystam z dwóch silników. Innymi słowy - raz uruchamiam jeden serwer gry na jednym silniku, raz na drugim (w którym akurat nie ma tych funkcji). I problem tego typu crashy występował na jednym i drugim.


Edit: jeszcze wyjaśnie - oczywiście "raz uruchamiam jeden serwer gry na jednym silniku, raz na drugim" - miałem na myśli, że np. jeden silnik jest używany przez 3 miesiące, a drugi przez miesiąc, pół roku - różnie. I tak na zmianę.

Nie że jednego dnia ten silnik, a drugiego dnia sobie zmieniam bo to by nie miało sensu.
P-179686
1 2 « 3 »
Poprzednia strona Strona 3 z 3