Jump to content

Core Crash - CHARACTER_MANAGER::Update


Recommended Posts

The problem only happens in gcc. 
The core crashes at a certain time when cutting stone.
Thanks to everyone who helped.

//Output GDB
#0  0x080a76eb in std::__invoke_impl<void, void (CHARACTER::* const&)(unsigned int), CHARACTER* const&, unsigned int const&> (
    __f=<synthetic pointer>: <optimized out>, __t=<error reading variable>, __f=<synthetic pointer>: <optimized out>, __t=<error reading variable>)
    at /usr/local/lib/gcc10/include/c++/bits/invoke.h:70
70          __invoke_impl(__invoke_memfun_deref, _MemFun&& __f, _Tp&& __t,
[Current thread is 1 (LWP 100113)]
(gdb) bt full
#0  0x080a76eb in std::__invoke_impl<void, void (CHARACTER::* const&)(unsigned int), CHARACTER* const&, unsigned int const&> (
    __f=<synthetic pointer>: <optimized out>, __t=<error reading variable>, __f=<synthetic pointer>: <optimized out>, __t=<error reading variable>)
    at /usr/local/lib/gcc10/include/c++/bits/invoke.h:70
No locals.
#1  std::__invoke<void (CHARACTER::* const&)(unsigned int), CHARACTER* const&, unsigned int const&> (__fn=<synthetic pointer>: <optimized out>)
    at /usr/local/lib/gcc10/include/c++/bits/invoke.h:95
No locals.
#2  std::_Mem_fn_base<void (CHARACTER::*)(unsigned int), true>::operator()<CHARACTER* const&, unsigned int const&> (this=<synthetic pointer>)
    at /usr/local/lib/gcc10/include/c++/functional:122
No locals.
#3  std::binder2nd<std::_Mem_fn<void (CHARACTER::*)(unsigned int)> >::operator() (__x=<error reading variable>, this=<synthetic pointer>)
    at /usr/local/lib/gcc10/include/c++/backward/binders.h:158
No locals.
#4  std::for_each<std::tr1::__detail::_Hashtable_iterator<CHARACTER*, true, false>, std::binder2nd<std::_Mem_fn<void (CHARACTER::*)(unsigned int)> > > (__last=...,
    __last=..., __f=..., __first=...) at /usr/local/lib/gcc10/include/c++/bits/stl_algo.h:3844
No locals.
#5  CHARACTER_MANAGER::Update (this=0xbfbfc97c, iPulse=20608) at char_manager.cpp:649
No locals.
#6  0x08144393 in idle () at main.cpp:532
        now = {tv_sec = 1663029283, tv_usec = 267220}
        passed_pulses = <optimized out>
        t = 824307
        pta = {tv_sec = 1663029283, tv_usec = 27560}
        process_time_count = 6
        now = {tv_sec = <optimized out>, tv_usec = <optimized out>}
        passed_pulses = <optimized out>
        t = <optimized out>
#7  idle () at main.cpp:507
        now = {tv_sec = <optimized out>, tv_usec = <optimized out>}
        passed_pulses = -1
        t = <optimized out>
        pta = {tv_sec = 1663029283, tv_usec = 27560}
        process_time_count = 6
#8  0x08057d95 in main (argc=1, argv=0xbfbfec90) at main.cpp:264
        sectree_manager = {<singleton<SECTREE_MANAGER>> = {_vptr.singleton = 0x83c6bf8 <vtable for SECTREE_MANAGER+8>, static ms_singleton = 0xbfbfbbac},
          static current_sectree_version = 768, m_map_pkSectree = {_M_t = {
              _M_impl = {<std::allocator<std::_Rb_tree_node<std::pair<unsigned int const, SECTREE_MAP*> > >> = {<__gnu_cxx::new_allocator<std::_Rb_tree_node<std::pair<unsigned int const, SECTREE_MAP*> > >> = {<No data fields>}, <No data fields>}, <std::_Rb_tree_key_compare<std::less<unsigned int> >> = {
                  _M_key_compare = {<std::binary_function<unsigned int, unsigned int, bool>> = {<No data fields>}, <No data fields>}}, <std::_Rb_tree_header> = {
                  _M_header = {_M_color = std::_S_red, _M_parent = 0x2aaf8ec0, _M_left = 0x2aaf8ec0, _M_right = 0x2aaf8ec0}, _M_node_count = 1}, <No data fields>}}},
          m_map_pkArea = {_M_t = {
              _M_impl = {<std::allocator<std::_Rb_tree_node<std::pair<int const, std::map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, TAreaInfo, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std--Type <RET> for more, q to quit, c to continue without paging--

//char_manager.cpp
void CHARACTER_MANAGER::Update(int32_t iPulse)
{
	BeginPendingDestroy();

	{
		if (!m_map_pkPCChr.empty())
		{
			auto callback = !(iPulse % PASSES_PER_SEC(5));

			std::for_each(m_map_pkPCChr.begin(), m_map_pkPCChr.end(),
				[&callback, &iPulse](const NAME_MAP::value_type& v)
				{
					auto ch = v.second;
					if (ch)
					{
						if (callback)
						{
							ch->ResetChatCounter();
							ch->CFSM::Update();
						}

						ch->UpdateCharacter(iPulse);
					}
				});
		}
	}

	{
		//Code causing crash
		if (!m_set_pkChrState.empty())
		{
#ifdef __GNUC__
			std::for_each(m_set_pkChrState.begin(), m_set_pkChrState.end(),
				std::bind2nd(std::mem_fn(&CHARACTER::UpdateStateMachine), iPulse));
#else
			std::for_each(m_set_pkChrState.begin(), m_set_pkChrState.end(),
				[iPulse](LPCHARACTER ch)
				{
					ch->UpdateStateMachine(iPulse);
				});
#endif
		}
	}

	{
		auto snapshot = CHARACTER_MANAGER::Instance().GetCharactersByRaceNum(xmas::MOB_SANTA_VNUM);
		if (!snapshot.empty())
		{
#ifdef __GNUC__
			std::for_each(snapshot.begin(), snapshot.end(),
				std::bind2nd(std::mem_fn(&CHARACTER::UpdateStateMachine), iPulse));
#else
			std::for_each(snapshot.begin(), snapshot.end(),
				[iPulse](LPCHARACTER ch)
				{
					ch->UpdateStateMachine(iPulse);
				});
#endif
		}
	}

	if (0 == (iPulse % PASSES_PER_SEC(3600)))
	{
		for (const auto& it : m_map_dwMobKillCount)
			DBManager::instance().SendMoneyLog(MONEY_LOG_MONSTER_KILL, it.first, it.second);

		m_map_dwMobKillCount.clear();
	}

	if (test_server && 0 == (iPulse % PASSES_PER_SEC(60)))
#ifdef __GNUC__
		sys_log(0, "CHARACTER COUNT vid %zu pid %zu", m_map_pkChrByVID.size(), m_map_pkChrByPID.size());
#else
		sys_log(0, "CHARACTER COUNT vid %Iu pid %Iu", m_map_pkChrByVID.size(), m_map_pkChrByPID.size());
#endif

	FlushPendingDestroy();
}

//stdafx.h
#ifdef __GNUC__
#include <tr1/unordered_map>
#include <tr1/unordered_set>
#define TR1_NS std::tr1
#else
#define TR1_NS std
#define isdigit iswdigit
#define isspace iswspace
#endif

 

Link to comment
Share on other sites

  • Premium

Mh, this is my update function (yes I removed the GNUC define). I also use GCC (v10 with std=c++2a) :

void CHARACTER_MANAGER::Update(int iPulse)
{
	BeginPendingDestroy();

	// PC character updates
	{
		if(!m_map_pkPCChr.empty())
		{
			// Copy container
			CHARACTER_VECTOR v;
			v.reserve(m_map_pkPCChr.size());
			transform(m_map_pkPCChr.begin(), m_map_pkPCChr.end(), back_inserter(v), boost::bind(&NAME_MAP::value_type::second, boost::placeholders::_1));

			if(0 == (iPulse % PASSES_PER_SEC(5)))
			{
				FuncUpdateAndResetChatCounter f;
				std::for_each(v.begin(), v.end(), f);
			}
			else
			{
				std::for_each(v.begin(), v.end(), [iPulse](auto&& arg) -> decltype(arg->UpdateCharacter(iPulse)) { return arg->UpdateCharacter(iPulse); });
			}
		}
	}

	// Monster Updates
	{
		if(!m_set_pkChrState.empty())
		{
			CHARACTER_VECTOR v;
			v.reserve(m_set_pkChrState.size());
			v.insert(v.end(), m_set_pkChrState.begin(), m_set_pkChrState.end());
			std::for_each(v.begin(), v.end(), [iPulse](auto&& arg) -> decltype(arg->UpdateStateMachine(iPulse)) { return arg->UpdateStateMachine(iPulse); });
		}
	}

	// Update separately Santa
	{
		CharacterVectorInteractor i;

		if(CHARACTER_MANAGER::instance().GetCharactersByRaceNum(xmas::MOB_SANTA_VNUM, i))
		{
			std::for_each(i.begin(), i.end(),
					[iPulse](auto&& arg) -> decltype(arg->UpdateStateMachine(iPulse)) { return arg->UpdateStateMachine(iPulse); });
		}
	}

	// Number of records once an hour hunt monsters
	if(0 == (iPulse % PASSES_PER_SEC(3600)))
	{
		for (auto it = m_map_dwMobKillCount.begin(); it != m_map_dwMobKillCount.end(); ++it)
			DBManager::instance().SendMoneyLog(MONEY_LOG_MONSTER_KILL, it->first, it->second);

		m_map_dwMobKillCount.clear();
	}

	// The test server every 60 seconds to count the number of characters
	if(g_bIsTestServer && 0 == (iPulse % PASSES_PER_SEC(60)))
		sys_log(0, "CHARACTER COUNT vid %zu pid %zu", m_map_pkChrByVID.size(), m_map_pkChrByPID.size());

	// Delayed DestroyCharacter to
	FlushPendingDestroy();
}

 

Edited by xXIntelXx
  • Love 1
Link to comment
Share on other sites

2 hours ago, xXIntelXx said:

Mh, this is my update function (yes I removed the GNUC define). I also use GCC (v10 with std=c++2a) :

void CHARACTER_MANAGER::Update(int iPulse)
{
	BeginPendingDestroy();

	// PC character updates
	{
		if(!m_map_pkPCChr.empty())
		{
			// Copy container
			CHARACTER_VECTOR v;
			v.reserve(m_map_pkPCChr.size());
			transform(m_map_pkPCChr.begin(), m_map_pkPCChr.end(), back_inserter(v), boost::bind(&NAME_MAP::value_type::second, boost::placeholders::_1));

			if(0 == (iPulse % PASSES_PER_SEC(5)))
			{
				FuncUpdateAndResetChatCounter f;
				std::for_each(v.begin(), v.end(), f);
			}
			else
			{
				std::for_each(v.begin(), v.end(), [iPulse](auto&& arg) -> decltype(arg->UpdateCharacter(iPulse)) { return arg->UpdateCharacter(iPulse); });
			}
		}
	}

	// Monster Updates
	{
		if(!m_set_pkChrState.empty())
		{
			CHARACTER_VECTOR v;
			v.reserve(m_set_pkChrState.size());
			v.insert(v.end(), m_set_pkChrState.begin(), m_set_pkChrState.end());
			std::for_each(v.begin(), v.end(), [iPulse](auto&& arg) -> decltype(arg->UpdateStateMachine(iPulse)) { return arg->UpdateStateMachine(iPulse); });
		}
	}

	// Update separately Santa
	{
		CharacterVectorInteractor i;

		if(CHARACTER_MANAGER::instance().GetCharactersByRaceNum(xmas::MOB_SANTA_VNUM, i))
		{
			std::for_each(i.begin(), i.end(),
					[iPulse](auto&& arg) -> decltype(arg->UpdateStateMachine(iPulse)) { return arg->UpdateStateMachine(iPulse); });
		}
	}

	// Number of records once an hour hunt monsters
	if(0 == (iPulse % PASSES_PER_SEC(3600)))
	{
		for (auto it = m_map_dwMobKillCount.begin(); it != m_map_dwMobKillCount.end(); ++it)
			DBManager::instance().SendMoneyLog(MONEY_LOG_MONSTER_KILL, it->first, it->second);

		m_map_dwMobKillCount.clear();
	}

	// The test server every 60 seconds to count the number of characters
	if(g_bIsTestServer && 0 == (iPulse % PASSES_PER_SEC(60)))
		sys_log(0, "CHARACTER COUNT vid %zu pid %zu", m_map_pkChrByVID.size(), m_map_pkChrByPID.size());

	// Delayed DestroyCharacter to
	FlushPendingDestroy();
}

 

Thank you. I asked a private question, I would appreciate it if you reply.

Link to comment
Share on other sites

  • Premium
4 minutes ago, JinxTheLux said:

Thank you. I asked a private question, I would appreciate it if you reply.

I saw, and I thought to have replied to the DM, but oh well :kekw:

 

Anyway, you worry about the container's copy but as I explained, your line is the same as the line in the original function (which is optimized anyway by the compiler, unless you ship a debug version for the live server). Therefore I don't see the need for the new snapshot class created.

Link to comment
Share on other sites

Please sign in to comment

You will be able to leave a comment after signing in



Sign In Now

Announcements



  • Similar Content

  • Activity

    1. 13

      Metin2 Closed Beta Content (2003-2004)

    2. 25

      [SRC] Metin2 on LINUX - The Old Metin2 Project

    3. 2

      United/Club/Midgard serverfiles?

    4. 13

      Metin2 Closed Beta Content (2003-2004)

    5. 13

      Metin2 Closed Beta Content (2003-2004)

  • Recently Browsing

    • No registered users viewing this page.
×
×
  • Create New...

Important Information

Terms of Use / Privacy Policy / Guidelines / We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.