[AGENT++] [BUG] Access to freed memory during startup of snmp++v3.2.24 with agent++v3.5.30

Jochen Katz katz at agentpp.com
Sun Jul 25 21:50:25 CEST 2010


Hi

to make it short: you're right. When calling log() from multiple threads
while instance is not yet set, anything can happen.

Until the next release the workaround is: Call init yourself or log
something before doing any other agent++/snmp++ call and don't call init
while any other thread could do some logging.

Regards,
  Jochen


Am 23.07.2010 12:43, schrieb Dominik Vogt:
> There is a bug in the startup code of the logging facility in snmp
> ++v3.2.24.  The problem depends on timing and sometimes causes access to
> already freed memory and sometimes even a crash.
> 
> In the class DefaultLog in log.h there are two inline functions:
> 
> 	static void init(AgentLog* logger) 
> 	  { if (instance) delete instance; instance = logger; }
> 
> 	static AgentLog* log() 
> 	  { if (!instance) init(new AgentLogImpl()); return instance; }
> 
> Obviously there is no protection agains parallel execution by multiple
> threads.  The first thread may have already instantiated the class in
> the init() function but not set the instance member when the second
> thread comes in, notices there is not yet an instance, calls init()
> again and deletes the now set instance member.  You know the story.
> 
> This actually does happen in threads.cpp fron agent++v3.5.30.  I'm not
> perfectly sure about the circumstances, but I believe it's like this:
> 
> 1. The TaskManager is created by calling its constructor:
> 
>   TaskManager::TaskManager(ThreadPool *tp, int stackSize):thread(*this)
>   {
>   	...
>   	thread.start();
>   	LOG_BEGIN(DEBUG_LOG | 1);
>   	LOG("TaskManager: thread started");
>   	LOG_END;
>   }
> 
> 2. The constructor starts a thread and then emits a log message.
> 
> 3. The current thread enters DefaultLog::log() and DefaultLog::init() as
> described above.
> 
> 4. The new thread enters the function thread_starter():
> 
> void* thread_starter(void* t)
> {
> 	Thread *thread = (Thread*)t;
> 	Thread::threadList.add(thread);
> 
> #ifndef NO_FAST_MUTEXES
> 	LOG_BEGIN(DEBUG_LOG | 1);
> 	LOG("Thread: started (tid)");
> 	LOG((int)(thread->tid));
> 	LOG_END;
> #endif
> 
> 5. There it also tries to emit a log message while the first thread is
> still initializing the DefaultLog.
> 
> (This is what I see in the stack traces from my debugging sessions.)
> 
> --
> 
> It's probably possible to work around the problem by simply calling
> DefaultLog::log() the the main() function of the application.
> 
> Ciao
> 
> Dominik ^_^  ^_^
> 
> _______________________________________________
> AGENTPP mailing list
> AGENTPP at agentpp.org
> http://lists.agentpp.org/mailman/listinfo/agentpp
> 



More information about the AGENTPP mailing list