dunno Temat założony przez niniejszego użytkownika |
» 2022-10-01 12:29:59 @DejaVu @pekfos Dzięki za wskazówki. Zrobiłem tak jak napisałeś tj. void ActionScript::internalAddPositionEx( lua_State * L, const PositionEx & pos ) { #ifdef MUTEXY_FIX std::lock_guard < std::mutex > guard( actionsMutex ); #endif lua_newtable( L ); setField( L, "z", pos.z ); setField( L, "y", pos.y ); setField( L, "x", pos.x ); setField( L, "stackpos", pos.stackpos ); }
oraz w actions.h pod protected: dodałem #ifdef MUTEXY_FIX mutable std::mutex actionsMutex; #endif to wywala błąd: actions.cpp: In static member function âstatic void ActionScript::internalAddPositionEx(lua_State*, const PositionEx&)â: actions.cpp:1175:37: error: invalid use of member âActionScript::actionsMutexâ in static member function std::lock_guard <std::mutex> guard(actionsMutex); ^~~~~~~~~~~~ In file included from player.h:10, from actions.cpp:8: actions.h:274:21: note: declared here mutable std::mutex actionsMutex; ^~~~~~~~~~~~
Próbowałem też innym sposobem tzn. Zwróciłeś uwage jak są zrobione locki w protocol76.cpp - gdybym tak zrobił analogicznie dla spells.cpp i actions.cpp i creature.cpp miałoby to sens? np. void ActionScript::internalAddPositionEx( lua_State * L, const PositionEx & pos ) { #ifdef MUTEXY_FIX OTSYS_THREAD_LOCK_CLASS lockClass( game->gameLock, "ActionScript::internalAddPositionEx()" ); #endif lua_newtable( L ); setField( L, "z", pos.z ); setField( L, "y", pos.y ); setField( L, "x", pos.x ); setField( L, "stackpos", pos.stackpos ); } z tym, że wywala podobny błąd: actions.cpp: In static member function âstatic void ActionScript::internalAddPositionEx(lua_State*, const PositionEx&)â: actions.cpp:1175:39: error: invalid use of member âActionScript::gameâ in static member function OTSYS_THREAD_LOCK_CLASS lockClass(game->gameLock, "ActionScript::internalAddPositionEx()"); ^~~~ In file included from player.h:10, from actions.cpp:8: actions.h:274:8: note: declared here Game *game; ^~~~
Na tyle rozumiem, że problem jest w tym ze jest zadeklarowana jako metoda statyczna tj: static void internalAddPositionEx( lua_State * L, const PositionEx & pos ); Da się jakoś inaczej obejsć ten problem niz kasujac slowo kluczowe static? Bo jak zmieniam ta metode kasujac słowo static to w ogóle zaczyna się krzaczyć w kilku innych miejscach. np. actions.cpp: In static member function âstatic int32_t ActionScript::internalGetPlayerInfo(lua_State*, ePlayerInfo)â: actions.cpp:1241:31: error: cannot call member function âvoid ActionScript::internalAddPositionEx(lua_State*, const PositionEx&)â without object internalAddPositionEx(L,pos); ^ actions.cpp:1246:31: error: cannot call member function âvoid ActionScript::internalAddPositionEx(lua_State*, const PositionEx&)â without object internalAddPositionEx(L,pos);
Oczywiście w actions.h mam kilka klas np. class ActionScript; class Action; Jeżeli chodzi np. już o Action::executeUse(......) to zadziałało bez problemu jednym i drugim sposobem np: bool Action::executeUse( Player * player, Item * item, PositionEx & posFrom, PositionEx & posTo ) { #ifdef MUTEXY_FIX OTSYS_THREAD_LOCK_CLASS lockClass( game->gameLock, "Action::executeUse()" ); #endif ale tutaj metoda już nie jest oznaczona jako "static" bool executeUse( Player * player, Item * item, PositionEx & posFrom, PositionEx & posTo ); Także jak sobie poradzić gdy metoda jest oznaczona jako static i chciałbym użyć np. #ifdef MUTEXY_FIX OTSYS_THREAD_LOCK_CLASS lockClass( game->gameLock, "ActionScript::internalAddPositionEx()" ); #endif |
|
pekfos |
» 2022-10-01 14:26:26 Mechanika gry wydaje się być z natury jednowątkowa, więc dodawanie tego tego muteksu w tym miejscu nie ma sensu. Trzeba to zrobić w Game, gdzie to już jest zrobione, pytanie tylko czy wszędzie gdzie powinno. W szczególności sprawdź te 10% własnego kodu, którego nie znamy. |
|
dunno Temat założony przez niniejszego użytkownika |
» 2022-10-01 17:31:10 @pekfos . Trzeba to zrobić w Game, gdzie to już jest zrobione, pytanie tylko czy wszędzie gdzie powinno. W szczególności sprawdź te 10% własnego kodu, którego nie znamy. Bazuje na tym: https://github.com/divinity76/YurOTS/tree/master/ots/source. W zasadzie mam tylko kilka innych dodatkowych funkcji do ktorych dodalem tez locka, wiem ze problem ten wystepował też na tym silniku co wyżej podałem link, a ja właściwie mam ten sam silnik. w gdb wywalalo ze problem dotyczy m.in. Game::playerUseItemEx, a tam jest lock. bool Game::playerUseItemEx( Player * player, const Position & posFrom, const unsigned char stack_from, const Position & posTo, const unsigned char stack_to, const uint16_t itemid ) { OTSYS_THREAD_LOCK_CLASS lockClass( gameLock, "Game::playerUseItemEx()" ); if( player->isRemoved ) return false; bool ret = false; Position thingpos = getThingMapPos( player, posFrom ); Item * item = dynamic_cast < Item * >( getThing( posFrom, stack_from, player ) ); if( item ) { std::map < uint16_t, Spell * >::iterator sit = spells.getAllRuneSpells()->find( item->getID() ); if( sit != spells.getAllRuneSpells()->end() ) { if(( abs( thingpos.x - player->pos.x ) > 1 ) ||( abs( thingpos.y - player->pos.y ) > 1 ) ) { player->sendCancel( "To far away..." ); ret = false; } else { std::string var = std::string( "" ); if( player->access >= g_config.ACCESS_PROTECT || sit->second->getMagLv() <= player->maglevel ) { bool success = sit->second->getSpellScript()->castSpell( player, posTo, var ); ret = success; if( success ) { autoCloseTrade( item ); item->setItemCharge( std::max(( int32_t ) item->getItemCharge() - 1, 0 ) ); if( item->getItemCharge() == 0 ) { if( removeThing( player, posFrom, item ) ) { FreeThing( item ); } } } } else { player->sendCancel( "You don't have the required magic level to use that rune." ); } } } else { actions.UseItemEx( player, posFrom, stack_from, posTo, stack_to, itemid ); ret = true; } } return ret; } bo rozumiem, ze jakby byl problem z inna funkcja, to gdb raczej by to wskazalo?, a tu ten lock jest. Może one po prostu nie działają prawidłowo? |
|
pekfos |
» 2022-10-01 17:54:17 bo rozumiem, ze jakby byl problem z inna funkcja, to gdb raczej by to wskazalo?, a tu ten lock jest. Nie. Problem nie musi dotyczyć tej funkcji i najprawdopodobniej nie dotyczy. Żeby dwa fragmenty kodu nie wykonywały się jednocześnie lock musi być w obu miejscach. Tu jest, więc patrzysz na zły kod. Przynajmniej dopóki rozważamy hipotezę błędnej synchronizacji. Wróć może do core dumpa i zobacz co robiły inne wątki w czasie gdy wywalił się ten jeden, który pokazałeś. Przy odrobinie szczęścia będzie drugi interesujący backtrace. |
|
dunno Temat założony przez niniejszego użytkownika |
» 2022-10-01 18:23:03 Żeby dwa fragmenty kodu nie wykonywały się jednocześnie lock musi być w obu miejscach.
No to nie bardzo rozumiem dlaczego w actions.cpp nie ma sensu go dodawać. Wróć może do core dumpa i zobacz co robiły inne wątki w czasie gdy wywalił się ten jeden, który pokazałeś. Przy odrobinie szczęścia będzie drugi interesujący backtrace.
Właśnie core dumpa nie mam zapisanego - nadpisał mi się przy robieniu restartu silnika gry. Poczekam, aż problem wystąpi ponownie, wtedy rozumiem, ze zrobić coś takiego: gdb ./otserv core np. jak mam skrypt lua to on wygląda tak: function onUse(cid, item, frompos, item2, topos) -- tutaj zawartość skryptu end
a właśnie w actions.cpp w oryginlnym executeuse miałem: bool Action::executeUse( Player * player, Item * item, PositionEx & posFrom, PositionEx & posTo ) { script->ClearMap(); script->_player = player; PositionEx playerpos = player->pos; uint32_t cid = script->AddThingToMap(( Thing * ) player, playerpos ); uint32_t itemid1 = script->AddThingToMap( item, posFrom ); lua_State * luaState = script->getLuaState(); lua_pushstring( luaState, "onUse" ); lua_gettable( luaState, LUA_GLOBALSINDEX ); lua_pushnumber( luaState, cid ); script->internalAddThing( luaState, item, itemid1 ); script->internalAddPositionEx( luaState, posFrom ); Thing * thing = script->game->getThing(( Position ) posTo, posTo.stackpos, player ); if( thing && posFrom != posTo ) { int32_t thingId2 = script->AddThingToMap( thing, posTo ); script->internalAddThing( luaState, thing, thingId2 ); script->internalAddPositionEx( luaState, posTo ); } else { script->internalAddThing( luaState, NULL, 0 ); PositionEx posEx; script->internalAddPositionEx( luaState, posEx ); } lua_pcall( luaState, 5, 1, 0 ); bool ret =( script->internalGetNumber( luaState ) != 0 ); return ret; } się do tego odwołuje tj lua_pushstring( luaState, "onUse" ); więc na pewno nie ma sensu w powyższej metodzie dodawać locka? a w zasadzie wszystko zaczyna się mniej więcej od void Protocol76::parseUseItemEx( NetworkMessage & msg ) { Position pos_from = msg.GetPosition(); uint16_t itemid = msg.GetItemId(); unsigned char from_stackpos = msg.GetByte(); Position pos_to = msg.GetPosition(); msg.GetU16(); unsigned char to_stackpos = msg.GetByte(); game->playerUseItemEx( player, pos_from, from_stackpos, pos_to, to_stackpos, itemid ); } i tutaj tez nie ma locka a dopiero potem idzie do game->playerUseItemEx i dopiero dalej do actions - nie wiem czy da coś dodanie locka w protocol76.cpp od ktorego się to zaczyna? Jeśli problem się powtórzy - a na pewno się powtórzy prędzej czy później, wszystko zależy od ilości graczy to skopiuje sobie tego core dumpa. I wrzucę co wyszło. |
|
pekfos |
» 2022-10-01 18:47:23 No to nie bardzo rozumiem dlaczego w actions.cpp nie ma sensu go dodawać. Cała logika gry powinna być wykonywana przez maksymalnie jeden wątek naraz, z czego wynika że skrypty lua są zawsze wykonywane przez maksymalnie jeden wątek naraz. Jeśli tak nie jest, to masz większy problem, na poziomie całej logiki gry. Lockiem w ActionScript co najwyżej zmniejszysz szanse na wystąpienie problemu, a w najgorszym razie wprowadzisz dodatkowe błędy w działaniu. |
|
dunno Temat założony przez niniejszego użytkownika |
» 2022-10-02 14:47:46 Cała logika gry powinna być wykonywana przez maksymalnie jeden wątek naraz, z czego wynika że skrypty lua są zawsze wykonywane przez maksymalnie jeden wątek naraz. Rozumiem, czyli w takim przypadku jeśli dodałbym locka do każdej metody w game.cpp nieważne czy byłby on niezbędny czy nie - to wtedy miałbym pewność, że locki są wszedzie tam gdzie powinny? |
|
pekfos |
» 2022-10-03 00:06:16 Nie, bo nie tylko metody Game korzystają z tych pól. |
|
1 « 2 » 3 |