Ru-MaNGOS

Ru-MaNGOS (http://mangos.ytdb.ru/index.php)
-   Баг-репорты (http://mangos.ytdb.ru/forumdisplay.php?f=27)
-   -   Краш на SaveToDB() (http://mangos.ytdb.ru/showthread.php?t=1626)

GriffonHeart 29.06.2010 12:02

Краш на SaveToDB()
 
Ревизия: 10105
Ядро: MaNGOS + insider42 + SD2
ACE: enable-builtin-ace
CONF: CFLAGS="-O1 -march=core2 -g -mssse3 -mfpmath=sse" CXXFLAGS="-O1 -march=core2 -g -mssse3 -mfpmath=sse"
OS: 2.6.34-gentoo-r1

Падает в функции Player::_SaveQuestStatus, в строке:

Код:

for( QuestStatusMap::iterator i = mQuestStatus.begin( ); i != mQuestStatus.end( ); ++i )
краш-дамп:

Код:

#0  0x00007f11a9005276 in std::_Rb_tree_increment(std::_Rb_tree_node_base*) () from /usr/lib/gcc/x86_64-pc-linux-gnu/4.4.4/libstdc++.so.6
(gdb) bt full
#0  0x00007f11a9005276 in std::_Rb_tree_increment(std::_Rb_tree_node_base*) () from /usr/lib/gcc/x86_64-pc-linux-gnu/4.4.4/libstdc++.so.6
No symbol table info available.
#1  0x000000000073551d in std::_Rb_tree_iterator<std::pair<unsigned int const, QuestStatusData> >::operator++ (this=<value optimized out>)
    at /usr/lib/gcc/x86_64-pc-linux-gnu/4.4.4/include/g++-v4/bits/stl_tree.h:184
No locals.
#2  Player::_SaveQuestStatus (this=<value optimized out>) at ../../../src/game/Player.cpp:17385
No locals.
#3  0x0000000000751e67 in Player::SaveToDB (this=0x7f112322d580) at ../../../src/game/Player.cpp:17102
        sql_name = {static npos = 18446744073709551615, _M_dataplus = {<std::allocator<char>> = {<__gnu_cxx::new_allocator<char>> = {<No data fields>}, <No data fields>},
            _M_p = 0x7f10e55ef5f8 "Кейдзо"}}
        ss = <incomplete type>
#4  0x00000000007560ab in Player::Update (this=0x7f112322d580, p_time=167) at ../../../src/game/Player.cpp:1437
        now = 1277800963
        pet = <value optimized out>
#5  0x00000000006a4165 in Map::Update (this=0x7f118dc297d0, t_diff=@0x7f118b4f6cbc) at ../../../src/game/Map.cpp:517
        plr = 0x7f10ff7e2060
        updater = {i_timeDiff = 692460616}
        grid_object_update = {i_visitor = @0x4c29b203}
        __FUNCTION__ = "Update"
        __PRETTY_FUNCTION__ = "virtual void Map::Update(const uint32&)"
        world_object_update = {i_visitor = @0x7f118b4f6be0}
#6  0x00000000006b287d in MapManager::Update (this=0x7f118dc29680, diff=<value optimized out>) at ../../../src/game/MapManager.cpp:249
        iter = {<std::tr1::__detail::_Hashtable_iterator_base<std::pair<unsigned int const, Map*>, false>> = {_M_cur_node = 0x7f118d98aa10, _M_cur_bucket = 0x2adffd00}, <No data fields>}
#7  0x000000000081c345 in World::Update (this=0x7f11a00237f0, diff=<value optimized out>) at ../../../src/game/World.cpp:1605
No locals.
#8  0x0000000000569965 in WorldRunnable::run (this=<value optimized out>) at ../../../src/mangosd/WorldRunnable.cpp:60
        diff = 167
        realCurrTime = 2195676949
        realPrevTime = <value optimized out>
        prevSleepTime = 0
#9  0x00000000008cb210 in ACE_Based::Thread::ThreadTask (param=0x7f10ff7e2060) at ../../../src/shared/Threading.cpp:187
        _task = 0x12d3920
#10 0x00007f11a92ad914 in start_thread () from /lib/libpthread.so.0
No symbol table info available.
#11 0x00007f11a88731dd in clone () from /lib/libc.so.6
No symbol table info available.
(gdb) quit

Объясните мне, как может ЗДЕСЬ возникнуть краш?
Пробовал:
1) Удалил mtmaps полностью
2) Обновил ядро операционной системы, gcc до вресии 4.4.4
3) Обновил glibc и весь софт
Краш происходит достаточно часто с попеременным успехом, может происходить не только на стадии сохранения квестов, но и на стадии сохранения ачивментов

tempura 29.06.2010 23:08

{<No data fields>}, <No data fields>},
пустые данные в базу пытается лить?

GriffonHeart 30.06.2010 02:22

Нет, краш происходит в Rb_tree_increment, предположительно в ++itr, поэтому и спрашиваю, как же так? :(
Бред бредом :-\

Inquisitor 30.06.2010 12:25

а сделай
# gcc -v
# /lib/libc.so.6

интересно, какие версии

RomanRom2 30.06.2010 12:36

пути стека неисповедимы, краш может показать где угодно. смотри по коду рядом. возможно и правда в базу не вливается. возможно таблица сломалась, возможно синтаксическая ошибка, возможно запись не нулл поля с пустым значеним, и т.д. и т.п.

LordJZ 30.06.2010 14:34

Да не, ошибку в SQL он в логе покажет.

Vladimir 30.06.2010 15:18

только если побитые данные в памяти вроде такое возможно...

Inquisitor 30.06.2010 22:27

Просто такое не у него одного. У меня тоже такое было, и не раз. Я бы сказал - постоянно.
Память живая 100%

GriffonHeart 01.07.2010 05:26

Цитата:

Сообщение от Inquisitor (Сообщение 9798)
а сделай
# gcc -v
# /lib/libc.so.6

интересно, какие версии

# gcc -v


#/lib/libc.so.6

xex 01.07.2010 07:04

VladimirMangos прочитай пожалуйста.

Цитата:

Сообщение от tempura (Сообщение 9759)
{<No data fields>}, <No data fields>},
пустые данные в базу пытается лить?

Немного не то. Но заметка правильная.
Я тоже ловлю краши, правда в других местах. И никак не могу отловить. Но пытаюсь =) В дебаге на локале всё замечательно, на лайв серве время от времени происходят :sorry:
Но, ноги от туда-же растут.
Ситуация такая - в одном месте выделили память, занесли туда значения, затем по ненадобности освободили её (иначе была бы утечка, чего не происходит), но в другом месте обращение идёт именно туда. Там уже естественно не то что ожидалось. Вот и ловим краш.

Эхх. Криво у нас всё. Шаг влево, шаг вправо - расстрел.
На Delphi есть замечательная функция, которая отладку на несколько порядков упрощает (я Delphi програмер лет 15 =) ):

procedure FreeAndNil(var Obj);
var
Temp: TObject;
begin
Temp := TObject(Obj);
Pointer(Obj) := nil;
Temp.Free;
end;

если подобную функцию использовать в движке для очистки, то сразу будет видно, где и что.

И ещё одно - почему не используется SEH? Переносимо на все платформы:
try
{
Я ща чёго-то натворю =)
}
catch
{
ShowMessage("Ой, сломалося, предположение такое-то");
}
Сразу будет видно, где и что.

Такое впечатление, что наши топовые разработчики отстали на лет 10.
Извиняюсь если резко, но это так.

P.S. Чтобы не быть голословным, выложу наколенный вариант утильки на Delphi, которую писАл, когда github глючил, для скачивания сорцов Карателя по HTTP. Заметьте, что даже для такой фигни (грубо говоря) в коде везде используется try - finally. Привычка целостности.
Вообще можно любое оттуда скачать (c гитхаба), только адрес указать нужный.
Может кому-то пригодится: http://slil.ru/29416531

P.P.S. Вот чесслово есть желание переписать всё ядро на Delphi. Таких проблем там в принципе быть не может. И ASM код лучше и быстрее. И все указатели защищены. И баги ловятся с полпинка. Но это утопия к сожалению =( ...

GriffonHeart 01.07.2010 12:48

Ловлю частые краши на выгрузке мобов/петов/игроков :(
Вот один из них:

Код:

#0  0x00007f2c5dd22165 in raise () from /lib/libc.so.6
(gdb) bt full
#0  0x00007f2c5dd22165 in raise () from /lib/libc.so.6
No symbol table info available.
#1  0x00007f2c5dd23580 in abort () from /lib/libc.so.6
No symbol table info available.
#2  0x00007f2c5dd5d58b in ?? () from /lib/libc.so.6
No symbol table info available.
#3  0x00007f2c5dd62b56 in ?? () from /lib/libc.so.6
No symbol table info available.
#4  0x00007f2c5dd6790c in free () from /lib/libc.so.6
No symbol table info available.
#5  0x00000000007ed46c in __gnu_cxx::new_allocator<std::_Rb_tree_node<std::pair<std::pair<unsigned int, SpellEffectIndex> const, Aura*> > >::deallocate (this=0x7f2b450967f0, i=...,
    mode=AURA_REMOVE_BY_DELETE) at /usr/lib/gcc/x86_64-pc-linux-gnu/4.4.4/include/g++-v4/ext/new_allocator.h:95
No locals.
#6  std::_Rb_tree<std::pair<unsigned int, SpellEffectIndex>, std::pair<std::pair<unsigned int, SpellEffectIndex> const, Aura*>, std::_Select1st<std::pair<std::pair<unsigned int, SpellEffectIndex> const, Aura*> >, std::less<std::pair<unsigned int, SpellEffectIndex> >, std::allocator<std::pair<std::pair<unsigned int, SpellEffectIndex> const, Aura*> > >::_M_put_node (this=0x7f2b450967f0, i=...,
    mode=AURA_REMOVE_BY_DELETE) at /usr/lib/gcc/x86_64-pc-linux-gnu/4.4.4/include/g++-v4/bits/stl_tree.h:363
No locals.
#7  std::_Rb_tree<std::pair<unsigned int, SpellEffectIndex>, std::pair<std::pair<unsigned int, SpellEffectIndex> const, Aura*>, std::_Select1st<std::pair<std::pair<unsigned int, SpellEffectIndex> const, Aura*> >, std::less<std::pair<unsigned int, SpellEffectIndex> >, std::allocator<std::pair<std::pair<unsigned int, SpellEffectIndex> const, Aura*> > >::_M_destroy_node (this=0x7f2b450967f0, i=...,
    mode=AURA_REMOVE_BY_DELETE) at /usr/lib/gcc/x86_64-pc-linux-gnu/4.4.4/include/g++-v4/bits/stl_tree.h:384
No locals.
#8  std::_Rb_tree<std::pair<unsigned int, SpellEffectIndex>, std::pair<std::pair<unsigned int, SpellEffectIndex> const, Aura*>, std::_Select1st<std::pair<std::pair<unsigned int, SpellEffectIndex> const, Aura*> >, std::less<std::pair<unsigned int, SpellEffectIndex> >, std::allocator<std::pair<std::pair<unsigned int, SpellEffectIndex> const, Aura*> > >::erase (this=0x7f2b450967f0, i=...,
    mode=AURA_REMOVE_BY_DELETE) at /usr/lib/gcc/x86_64-pc-linux-gnu/4.4.4/include/g++-v4/bits/stl_tree.h:1348
No locals.
#9  std::multimap<std::pair<unsigned int, SpellEffectIndex>, Aura*, std::less<std::pair<unsigned int, SpellEffectIndex> >, std::allocator<std::pair<std::pair<unsigned int, SpellEffectIndex> const, Aura*> > >::erase (this=0x7f2b450967f0, i=..., mode=AURA_REMOVE_BY_DELETE) at /usr/lib/gcc/x86_64-pc-linux-gnu/4.4.4/include/g++-v4/bits/stl_multimap.h:503
No locals.
#10 Unit::RemoveAura (this=0x7f2b450967f0, i=..., mode=AURA_REMOVE_BY_DELETE) at ../../../src/game/Unit.cpp:4637
        Aur = 0x7f2b4509d090
        AurSpellInfo = 0x7f2c51990a64
        statue = <value optimized out>
#11 0x00000000007ed74f in Unit::RemoveAllAuras (this=0x7f2b450967f0, mode=AURA_REMOVE_BY_DELETE) at ../../../src/game/Unit.cpp:4697
        iter = {_M_node = 0x7f2b4509d110}
#12 0x00000000007f9fe6 in Unit::CleanupsBeforeDelete (this=0x7f2b450967f0) at ../../../src/game/Unit.cpp:12575
No locals.
#13 0x0000000000696268 in Map::AddObjectToRemoveList (this=0x7f2c445bfa00, obj=0x7f2b450967f0) at ../../../src/game/Map.cpp:1444
        __FUNCTION__ = "AddObjectToRemoveList"
        __PRETTY_FUNCTION__ = "void Map::AddObjectToRemoveList(WorldObject*)"
#14 0x00000000006bfdbc in WorldObject::AddObjectToRemoveList (this=0x2fd8) at ../../../src/game/Object.cpp:1711
No locals.
#15 0x000000000073e396 in Player::RemovePet (this=0x7f2b3092aaf0, pet=0x7f2b450967f0, mode=PET_SAVE_AS_CURRENT, returnreagent=true) at ../../../src/game/Player.cpp:17932
No locals.
#16 0x00000000008235a5 in WorldSession::LogoutPlayer (this=0x7f2b4e874d80, Save=true) at ../../../src/game/WorldSession.cpp:398
        guild = 0x0
        _map = <value optimized out>
        data = {<ByteBuffer> = {static DEFAULT_SIZE = 4096, _rpos = 80, _wpos = 139828176964303, _storage = {<std::_Vector_base<unsigned char, std::allocator<unsigned char> >> = {
                _M_impl = {<std::allocator<unsigned char>> = {<__gnu_cxx::new_allocator<unsigned char>> = {<No data fields>}, <No data fields>}, _M_start = 0x7f2b9e949610 "`",
                  _M_finish = 0x7f2c5dd679f0 "H\205\300H\211\303\017\204\244", _M_end_of_storage = 0x42c14200 "\020\002"}}, <No data fields>}}, m_opcode = 32}
#17 0x0000000000823c78 in ~WorldSession (this=0x2fb2, __in_chrg=<value optimized out>) at ../../../src/game/WorldSession.cpp:65
        packet = <value optimized out>
#18 0x000000000081bd0d in World::AddSession_ (this=0x7f2c580237f0, s=0x7f2b4547e0c0) at ../../../src/game/World.cpp:226
        __FUNCTION__ = "AddSession_"
        __PRETTY_FUNCTION__ = "void World::AddSession_(WorldSession*)"
        packet = {<ByteBuffer> = {static DEFAULT_SIZE = 4096, _rpos = 13210480, _wpos = 9208889, _storage = {<std::_Vector_base<unsigned char, std::allocator<unsigned char> >> = {
                _M_impl = {<std::allocator<unsigned char>> = {<__gnu_cxx::new_allocator<unsigned char>> = {<No data fields>}, <No data fields>}, _M_start = 0x7f2c48d14c80 "\260L\321H,\177",
                  _M_finish = 0x8c7f25 "\211\350H\203\304h[]A\\A]A^A_\303H\211\\$\320H\211l$\330L\211d$\340L\211l$\350L\211t$\360L\211|$\370H\203\354hI\211\374I\211\365I\211\326H\211˾",
                  _M_end_of_storage = 0x7f2c48d14c00 "\020#\003\a"}}, <No data fields>}}, m_opcode = 38842}
        pkt = {<ByteBuffer> = {static DEFAULT_SIZE = 4096, _rpos = 0, _wpos = 139828176964640, _storage = {<std::_Vector_base<unsigned char, std::allocator<unsigned char> >> = {
                _M_impl = {<std::allocator<unsigned char>> = {<__gnu_cxx::new_allocator<unsigned char>> = {<No data fields>}, <No data fields>}, _M_start = 0x7f2c48d14c30 "",
---Type <return> to continue, or q <return> to quit---
                  _M_finish = 0x7f2c48d14bf0 " L\321H,\177", _M_end_of_storage = 0x7f2c48d14c80 "\260L\321H,\177"}}, <No data fields>}}, m_opcode = 30988}
        decrease_session = true
        Sessions = <value optimized out>
        pLimit = <value optimized out>
        QueueSize = <value optimized out>
#19 0x000000000081c652 in World::UpdateSessions (this=0x7f2c580237f0, diff=211) at ../../../src/game/World.cpp:2023
        sess = 0x7f2b4547e0c0
#20 0x000000000081cf99 in World::Update (this=0x7f2c580237f0, diff=<value optimized out>) at ../../../src/game/World.cpp:1452
No locals.
#21 0x0000000000569de5 in WorldRunnable::run (this=<value optimized out>) at ../../../src/mangosd/WorldRunnable.cpp:60
        diff = 211
        realCurrTime = 2371419823
        realPrevTime = <value optimized out>
        prevSleepTime = 0
#22 0x00000000008cc610 in ACE_Based::Thread::ThreadTask (param=0x2fb2) at ../../../src/shared/Threading.cpp:187
        _task = 0x7f2c397bdb40
#23 0x00007f2c5e7fb914 in start_thread () from /lib/libpthread.so.0
No symbol table info available.
#24 0x00007f2c5ddc11dd in clone () from /lib/libc.so.6
No symbol table info available.

Если включить выгрузку гридов, то вообще караул будет :(

selector 01.07.2010 14:16

GriffonHeart
Изменил в Конфиге у себя. Краши пропали. До правки серв падал каждые полчаса-час.
Код:

CharLogFile = ""
CharLogTimestamp = 0
CharLogDump = 0

Теперь ловлю частые краши с инстами "InstanceMap::Add(Player *player)"

Поставил данный фикс:
Код:

------------------------------- src/game/Map.cpp -------------------------------
index 055ec2a..e20e1df 100644
@@ -1821,7 +1821,9 @@ bool InstanceMap::Add(Player *player)
                        GetInstanceSave()->GetMapId(), GetInstanceSave()->GetInstanceId(),
                        GetInstanceSave()->GetDifficulty(), GetInstanceSave()->GetPlayerCount(),
                        GetInstanceSave()->GetGroupCount(), GetInstanceSave()->CanReset());
-                    ASSERT(false);
+                    //ASSERT(false);
+                                        player->RepopAtGraveyard();
+                                        return false;
                }
            }
            else
@@ -1845,6 +1847,8 @@ bool InstanceMap::Add(Player *player)
                                groupBind->save->GetMapId(), groupBind->save->GetInstanceId(), groupBind->save->GetDifficulty(),
                                groupBind->save->GetPlayerCount(), groupBind->save->GetGroupCount(), groupBind->save->CanReset());
                        //ASSERT(false);
+                                                player->RepopAtGraveyard();
+                                                return false;
                    }
                    // bind to the group or keep using the group save
                    if (!groupBind)
@@ -1888,9 +1892,11 @@ bool InstanceMap::Add(Player *player)
                    // set up a solo bind or continue using it
                    if(!playerBind)
                        player->BindToInstance(GetInstanceSave(), false);
-                    //else
+                    else
                        // cannot jump to a different instance without resetting it
                        //ASSERT(playerBind->save == mapSave);
+                                                player->RepopAtGraveyard();
+                                                return false;
                }
            }
        }

о стабильности сообщу как появятся результаты.

LordJZ 01.07.2010 15:00

Цитата:

Сообщение от selector (Сообщение 9898)
...
Код:

------------------------------- src/game/Map.cpp -------------------------------
index 055ec2a..e20e1df 100644
...
@@ -1888,9 +1892,11 @@ bool InstanceMap::Add(Player *player)
                    // set up a solo bind or continue using it
                    if(!playerBind)
                        player->BindToInstance(GetInstanceSave(), false);
-                    //else
+                    else
                        // cannot jump to a different instance without resetting it
                        //ASSERT(playerBind->save == mapSave);
+                        player->RepopAtGraveyard();
+                        return false;
                }
            }
        }

...

Кхм, так делать нельзя. Грубейшая ошибка.

GriffonHeart 01.07.2010 16:15

Цитата:

Сообщение от selector (Сообщение 9898)
GriffonHeart
Изменил в Конфиге у себя. Краши пропали. До правки серв падал каждые полчаса-час.
Код:

CharLogFile = ""
CharLogTimestamp = 0
CharLogDump = 0


Не совсем понимаю, как чар-лог может быть связан с теми бэк-трейсами, что я выкладывал... но всё-таки отключу, ибо эта функция мне давно не нужна, только место на винте сжирала.

tempura 01.07.2010 18:05

Кстати... Я правильно понимаю, что ни на чистом ядре, ни на венде, подобного не наблюдается? То есть это всплывает лишь под *никс, или же на ядре insider42?

GriffonHeart 01.07.2010 18:47

Не знаю. Но я уже в панике, мне юзеры мозг съели.
Наверно придётся пределать сервер под "чистый" мангос и проверить, будет ли падать :-\ О результатах конечно сообщу...

PS: Даже с отключенным CharLogFile падает

Vladimir 01.07.2010 22:22

Конечно может еще что-то с gcc оптимизацией кода.

Цитата:

VladimirMangos прочитай пожалуйста.
xex, меньше умничайте...

1. Те кто комментируют assert-ы и предлагают разный перехваты exceptions
должны понимать что иногда лучше упасть серверу чем получить геморой со
некоторой вероятность нарушенных данных в базе для играков.

2. Где вы приведенному куске кода увидели освобождение памяти и не обнуленные указатели. Там _статическая_ на момент началей куска кода структура в которое (a) итератор не может нигде стаить инвалидным в процессе ее выполгнения
(b) изменяется тоько одно поле _не_указатель_ в структуре. Т.е. или проблема с генерированным кодом самим компилятором, или структура на вызов куска кода уже нарушена по содержанию (как я предположил ранее), или какой-то из вызываемого кода пишет куда попало и разрушает структуру в процессе - учитывае код - это работа с запросами к базе - но если бы там были такие проблемы - мы бы заметили бы это горазда чаще.

3) как вам обнуление указателся поможет решить проблему с другим указателем в совершенно другом месте на тот-же удаленный объект. Обычно проблемы не с не-обнуленным указателем при удалении, а с альтернативным указателем на удаленный объекта.

Так что иногда лучше читать чем писать... передовой вы наш...

Dereka 03.07.2010 09:57

запустите с valgrind
сразу увидите все места где память corrupted


Текущее время: 06:42. Часовой пояс GMT +3.

ru-mangos.ru - Русское сообщество MaNGOS