Dead lock sometimes happens, I guess it is in CC.
I try to find some pattern which are the answers describe in 
What are common reasons for deadlocks?void cbThreadPool::AddTask(cbThreadedTask *task, bool autodelete)
{
  if (!task)
    return;
  wxMutexLocker lock(m_Mutex);
  m_tasksQueue.push_back(cbThreadedTaskElement(task, autodelete));
  m_taskAdded = true;
  // we are in batch mode, so no need to awake the idle thread
  // m_workingThreads < m_concurrentThreads means there are some threads in idle mode (no task assigned)
  if (!m_batching && m_workingThreads < m_concurrentThreads)
    AwakeNeeded();
}
 In main thread:In void Parser::OnBatchTimer(cb_unused wxTimerEvent& event)
    bool send_event          = true;
    bool sendStartParseEvent = false;
    if (   !m_BatchParseFiles.empty()
        || !m_PredefinedMacros.IsEmpty() )
    {
        CC_LOCKER_TRACK_P_MTX_LOCK(ParserCommon::s_ParserMutex)
        ParserThreadedTask* thread = new ParserThreadedTask(this, ParserCommon::s_ParserMutex);
        TRACE(_T("Parser::OnBatchTimer(): Adding a ParserThreadedTask thread to m_Pool."));
        m_Pool.AddTask(thread, true); //once this function is called, the thread will be executed from the pool.
        if (ParserCommon::s_CurrentParser)
            send_event = false;
        else // Have not done any batch parsing yet -> assign parser
        {
            ParserCommon::s_CurrentParser = this;
            m_StopWatch.Start(); // reset timer
            sendStartParseEvent = true;
        }
        CC_LOCKER_TRACK_P_MTX_UNLOCK(ParserCommon::s_ParserMutex)
    }
Or
bool Parser::Done()
{
    CC_LOCKER_TRACK_P_MTX_LOCK(ParserCommon::s_ParserMutex)
    bool done = m_BatchParseFiles.empty()
                && m_PredefinedMacros.IsEmpty()
                && !m_NeedMarkFileAsLocal
                && m_Pool.Done();
    CC_LOCKER_TRACK_P_MTX_UNLOCK(ParserCommon::s_ParserMutex)
    return done;
}
 In worker thread:int ParserThreadedTask::Execute()
    CC_LOCKER_TRACK_P_MTX_UNLOCK(m_ParserMutex);
    if (m_Parser->m_IgnoreThreadEvents)
        m_Parser->m_IsFirstBatch = true;
    TRACE(_T("ParserThreadedTask::Execute(): Parse source files"));
    while (!batchFiles.empty())
    {
        TRACE(_T("-ParserThreadedTask::Execute(): Parse %s"), batchFiles.front().wx_str());
        m_Parser->Parse(batchFiles.front()); // bool isLocal = true, bool locked = false
        batchFiles.pop_front();
    }
    CC_LOCKER_TRACK_P_MTX_LOCK(m_ParserMutex)
All the patterns are:
lock the parser mutex
lock the pool
release the pool
release the parser mutex
Is it the bad code pattern which may cause dead lock?
EDIT: It looks like the answer is NO. 
