Hi, Huki, thanks, would you mind to update your local copy of C::B to the latest SVN? I have some tiny issue to apply your patch, though I can manually applied it, but it looks like some of the code I have already changed.
Oh, sorry about that. I'm in fact planning on moving some of my projects to git very soon and if everything goes well I'll be updating to obf's repo here
https://github.com/obfuscated/codeblocks_sf. In the meantime I'm trying to get some of the small patches in (just a few more actually).
BTW, in one testing branch of my local copy, I have try to remove all the lockers in CC (locker of the Parser and locker of the TokenTree), also, I remove the m_PoolTask, it was introduced to handle the priority header files, but now, we can already recursive to parse the included files, so I don't think m_PoolTask is needed any longer. Also, my local branch has many other issues I need to fix, so it will take a long time before I publish the patches
The CC code indeed needs some cleanup since we don't use the priority headers. It's good if the m_PoolTask can be removed, and while it's here I think it does needs to be protected since the last time I checked it was accessed from different threads..
Btw, though I'm using an old revision I do check the latest revisions of files which I've modified, to make sure my fix is still relevant. For this one (i.e., the mutex deadlock) I noticed no changes so I was quite sure the bug still exists in the newer revisions. It's very strange that you and White-Tiger are unable to reproduce it. Let me explain:
When calling DeleteParser() we lock the parser mutex before calling TerminateAllThreads():
Parser::~Parser()
{
CC_LOCKER_TRACK_P_MTX_LOCK(ParserCommon::s_ParserMutex)
DisconnectEvents();
TerminateAllThreads();
[...]
CC_LOCKER_TRACK_P_MTX_UNLOCK(ParserCommon::s_ParserMutex)
}
In TerminateAllThreads(), we send the request to abort all threads, and wait in a while loop till all threads have aborted:
m_Pool.AbortAllTasks();
while (!m_Pool.Done())
wxMilliSleep(1);
At this time if one of the worker threads has already been executed, you can see in the Execute call that it would enter and leave the parser mutex many times during the course of the call:
int ParserThreadedTask::Execute()
{
TRACE(_T("ParserThreadedTask::Execute(): Enter"));
if (!m_Parser) return 0;
CC_LOCKER_TRACK_P_MTX_LOCK(m_ParserMutex)
[...]
CC_LOCKER_TRACK_P_MTX_UNLOCK(m_ParserMutex);
[...]
CC_LOCKER_TRACK_P_MTX_LOCK(m_ParserMutex)
[...]
And if Execute() is waiting to enter this mutex while we are doing the while loop in TerminateAllThreads(), we would never return. FYI, I had confirmed this condition when checking this bug under debugger.
Now, the m_Pool object happens to keep it's own mutex to protect calls to it from multiple threads, so there doesn't seem to be any reason to use the parser mutex around the m_Pool object. So in my patch I had removed the lock around the while loop, and also around the DisconnectEvents() call in ~Parser().