Заказать игровой сервер Контакты (заказать плагин/исправить ошибки/другое) Пожертвовать Поиск

[ вход ]
[ последние сообщения ]

  • Страница 1 из 1
  • 1
Падает сервер
Entity Дата: Пятница, 03.11.2017, 17:42:45 | Сообщение # 1
Сообщений: 67
Репутация: 1 [ +/- ]
Здравствуйте. Такая проблема мучает. Почти каждый день (1-2 раза в день) сервер падает на смене карты. До смены карты сервер не лагает. Возможно, дело в утечке памяти. Плагинов своих много, скоро пересмотрю весь код на наличие утечек. Как думаете, в чем проблема? Может кто сталкивался с этим...
 
Nail Дата: Суббота, 04.11.2017, 17:42:51 | Сообщение # 2
Сообщений: 38
Репутация: 8 [ +/- ]
Можно сдампить хэндлы и посмотреть что там с потреблением памяти. Последний сорсмод сам хорошо с утечками справляется и всё логирует т.ч. многого ждать не стоит. Еще есть инструмент accelerator, он выдает трэйсстэк при краше. По нему можно вычислить сбоящий экстеншин или сбой в двиге. По стэку видно какая функция не отработала а по ней можно уже определить и спэшник, который формирует плохой запрос. То, что крашит часто - это хорошо, можно методом исключения найти плохой плагин. Надо разбить список плагинов на 2 и первый день проверять первую половину, второй вторую затем еще разбить на 2 и т.д. так можно выйти на баговый плагин за несколько дней. Главное делать выдержку с запасом т.к. баговых плагинов может быть несколько и если один из них пропустить, придется начинать заново.
Есть еще железный метод - добавить логирование в плагины на начало вызова функций и на конец. При краше в логах будет видно какая функция была вызвана но не завершилась.


Сообщение отредактировал Nail - Воскресенье, 05.11.2017, 14:19:20
 
Entity Дата: Среда, 08.11.2017, 11:33:08 | Сообщение # 3
Сообщений: 67
Репутация: 1 [ +/- ]
Nail, спасибо большое) попробую сначала accelerator'om. Может без лишней заморочки проблему сразу выявлю)

Добавлено (08.11.2017, 11:33:08)
---------------------------------------------
Nail, отловил acceletor'om такое вот:

0 engine_srv.so!CFrameSnapshotManager::RemoveEntityReference(int) + 0x15
1 engine_srv.so!CFrameSnapshotManager::DeleteFrameSnapshot(CFrameSnapshot*) + 0x4b
2 engine_srv.so!CFrameSnapshot::ReleaseReference() + 0x2c
3 engine_srv.so!CClientFrame::SetSnapshot(CFrameSnapshot*) + 0x3a
4 engine_srv.so!CClientFrame::SetSnapshot(CFrameSnapshot*) + 0x70
5 engine_srv.so!CClientFrameManager::FreeFrame(CClientFrame*) + 0x28
6 engine_srv.so!CClientFrameManager::DeleteClientFrames(int) + 0x40
7 engine_srv.so!CGameClient::UpdateAcknowledgedFramecount(int) + 0x75
8 engine_srv.so!NET_Tick::Process() + 0x18
9 engine_srv.so!CNetChan::ProcessMessages(bf_read&) + 0x2fa
10 engine_srv.so!CNetChan::ProcessPacket(netpacket_s*, bool) + 0x33b
11 engine_srv.so!NET_ProcessSocket(int, IConnectionlessPacketHandler*) + 0x3ae
12 engine_srv.so!CBaseServer::RunFrame() + 0x14f
13 engine_srv.so!SV_Frame(bool) + 0x13e
14 engine_srv.so!_Host_RunFrame_Server(bool) + 0x177
15 engine_srv.so!_Host_RunFrame(float) + 0x441
16 engine_srv.so!Host_RunFrame(float) + 0x248
17 engine_srv.so!CHostState::State_Run(float) + 0xe1
18 engine_srv.so!CHostState::FrameUpdate(float) + 0x9e
19 engine_srv.so!HostState_Frame(float) + 0x19
20 engine_srv.so!CEngine::Frame() + 0x38e
21 engine_srv.so!CDedicatedServerAPI::RunFrame() + 0x26
22 dedicated_srv.so!RunServer() + 0x42
23 engine_srv.so!CModAppSystemGroup::Main() + 0x9d
24 engine_srv.so!CAppSystemGroup::Run() + 0x30
25 engine_srv.so!CDedicatedServerAPI::ModInit(ModInfo_t&) + 0x1df
26 dedicated_srv.so!CDedicatedAppSystemGroup::Main() + 0x93
27 dedicated_srv.so!CAppSystemGroup::Run() + 0x30
28 dedicated_srv.so!CAppSystemGroup::Run() + 0x30
29 dedicated_srv.so!main + 0x1c6
30 srcds_linux + 0x9b9
31 libc-2.17.so + 0x19933
32 ld-2.17.so + 0x14fa0
33 libc-2.17.so + 0x19849
34 ld-2.17.so + 0xf930

не особо понятно, что и как косячит :)

 
Nail Дата: Пятница, 10.11.2017, 18:12:03 | Сообщение # 4
Сообщений: 38
Репутация: 8 [ +/- ]
Судя по трейсу всё плохо. Следов экстеншинов и самих sourcemod/metamod нету т.е. это или баг самого двига или что-то косвенным образом вызывает краш. Возможно один из плагинов меняет какую-то переменную, которая вызывает сбой при исполнении этой функции или же где-то повреждается память. Функция RemoveEntityReference - часть сетевого модуля, в ней выполняется очистка пакетов энтит, сложно представить что какой-то плагин может внедряться так глубоко в этот модуль.

Код
void CFrameSnapshotManager::RemoveEntityReference( PackedEntityHandle_t handle )
{
    Assert( handle != INVALID_PACKED_ENTITY_HANDLE );

    PackedEntity *packedEntity = m_PackedEntities[ handle ];

    if ( --packedEntity->m_ReferenceCount <= 0)
    {
  AUTO_LOCK_FM( m_WriteMutex );

  m_PackedEntities.Remove( handle );
  m_PackedEntitiesPool.Free( packedEntity );

  // if we have a uncompression cache, remove reference too
  FOR_EACH_VEC( m_PackedEntityCache, i )
  {
   UnpackedDataCache_t &pdc = m_PackedEntityCache[i];
   if ( pdc.pEntity == packedEntity )
   {
    pdc.pEntity = NULL;
    pdc.counter = 0;
    break;
   }
  }
    }
}


Я бы рекомендовал карантин плагинов с использованием бинарного (логарифмического) разделения плагонов. Т.е.на каждом шаге дробить список оставшихся плагинов на 2 и проверять половины.
Если есть знания в области написания экстеншинов, можно подключиться к этой функции и посмотреть что там происходит. Хэндл можно из детоура вынуть (если функция не виртуальная) и оффсет для packedEntity выудить через иду... можно и через саму иду дебажить, но придется мириться с лагами. Впрочем, по этой части у меня мало опыта, может в вашем случае это будет весьма сносный вариант.

Код
int __cdecl CFrameSnapshotManager::RemoveEntityReference(int a1, int a2)
{
  int result; // eax@1
  unsigned __int8 v3; // zf@1
  int v4; // edi@3
  int v5; // ecx@6
  int v6; // edi@7
  int v7; // eax@7
  int v8; // edx@8

  result = *(_DWORD *)(a2 + 12) - 1;
  v3 = *(_DWORD *)(a2 + 12) == 1;
  *(_DWORD *)(a2 + 12) = result;
  if ( result < 0 | v3 )
  {
    v4 = ThreadGetCurrentId();
    if ( v4 == *(_DWORD *)(a1 + 16488) || (unsigned __int8)ThreadInterlockedAssignIf(a1 + 16488, v4, 0) )
    {
      ++*(_DWORD *)(a1 + 16492);
    }
    else
    {
      _mm_pause();
      CThreadFastMutex::Lock(a1 + 16488, v4, 0);
    }
    PackedEntity::_PackedEntity(a2);
    CUtlMemoryPool::Free(a1 + 32, a2);
    v5 = *(_DWORD *)(a1 + 96);
    if ( v5 > 0 )
    {
      v6 = *(_DWORD *)(a1 + 84);
      v7 = 0;
      if ( *(_DWORD *)v6 == a2 )
      {
        v8 = *(_DWORD *)(a1 + 84);
LABEL_13:
        *(_DWORD *)v8 = 0;
        *(_DWORD *)(v8 + 4) = 0;
      }
      else
      {
        while ( 1 )
        {
          ++v7;
          if ( v7 == v5 )
            break;
          v8 = v6 + 16396 * v7;
          if ( *(_DWORD *)v8 == a2 )
            goto LABEL_13;
        }
      }
    }
    --*(_DWORD *)(a1 + 16492);
    result = *(_DWORD *)(a1 + 16492);
    if ( !result )
      result = ThreadInterlockedExchange(a1 + 16488, 0);
  }
  return result;
}


Псевдокод из иды для CSS, вероятно в GO ситуация особо и не изменилась. Можно по оффсету посмотреть примерно где сбойнул... на глаз это начало функции.
Функция не виртуальная и не статическая, подойдет Detour Member Hook


Сообщение отредактировал Nail - Пятница, 10.11.2017, 18:23:36
 
Entity Дата: Пятница, 10.11.2017, 23:21:45 | Сообщение # 5
Сообщений: 67
Репутация: 1 [ +/- ]
Nail, хммм, интересненько. Попробую бинарным разделением плагинов найти виновника, для начала. В общем, понял Вас. Спасибо большое klas


Сообщение отредактировал Entity - Пятница, 10.11.2017, 23:22:04
 
  • Страница 1 из 1
  • 1
Поиск: