views:

251

answers:

3

I have to program a simple threaded program with MFC/C++ for a uni assignment.

I have a simple scenario in wich i have a worker thread which executes a function along the lines of :

UINT createSchedules(LPVOID param)
{
  genProgThreadVal* v = (genProgThreadVal*) param;
  // v->searcherLock is of type CcriticalSection*
  while(1)
  {
    if(v->searcherLock->Lock())
    {
      //do the stuff, access shared object , exit clause etc..
      v->searcherLock->Unlock();
    }
  }
  PostMessage(v->hwnd, WM_USER_THREAD_FINISHED , 0,0);
  delete v;
  return 0;
}

In my main UI class, i have a CListControl that i want to be able to access the shared object (of type std::List). Hence the locking stuff. So this CList has an handler function looking like this :

void Ccreationprogramme::OnLvnItemchangedList5(NMHDR *pNMHDR, LRESULT *pResult)
{
  LPNMLISTVIEW pNMLV = reinterpret_cast<LPNMLISTVIEW>(pNMHDR);
  if((pNMLV->uChanged & LVIF_STATE) 
    && (pNMLV->uNewState & LVNI_SELECTED))
  {    
    searcherLock.Lock();
    // do the stuff on shared object
    searcherLock.Unlock();

    // do some more stuff
  }
  *pResult = 0;
}

The searcherLock in both function is the same object. The worker thread function is passed a pointer to the CCriticalSection object, which is a member of my dialog class.

Everything works but, as soon as i do click on my list, and so triggers the handler function, the whole program hangs indefinitely.I tried using a Cmutex. I tried using a CSingleLock wrapping over the critical section object, and none of this has worked. What am i missing ?

EDIT: I found the solution, thanks to the amazing insight of Franci. That'll teach me to not put every bit of the code into the question. Thanks !

+4  A: 

Are you sure the background thread is not doing anything that would SendMessage to the UI thread between the Lock and Unlock?

If it does, it'll be blocked until the message queue processes that message; however, the message queue will never get to it, since it's blocked in the middle of processing the item changed notification of the list view.

Franci Penov
Thanks that was the problem. I originally sent a message to the UI thread between the lock and unlock, and then removed it and replaced it by a direct call to the said function (hackish, i know). Anyway if get the call to this function back into a PostMessage, but out of the lock/unlock, it works fine.Thank you very much ! Great insight
raph.amiard
+1, psychic debugging powerz.
Hans Passant
@nobugz - after several years of debugging various instances of STA COM deadlocks, it's easy to spot the pattern. :-)
Franci Penov
A: 

I notice that you delete v; in createSchedules(). Why?

It makes me wonder if searcherLock really refers to the same object in both functions. If the lock isn't in the same memory location it certainly won't work.

Also, locks or critical sections must be initialized with the proper state. You don't show that code so I can't tell. But if you didn't initialize it, it will have bad contents and will certainly break.

Do some debugging by using TRACE macros (I think that is what you use in MSVC) to output &searcherLock (the memory location of searcherLock) in both functions to guarantee they are the same object.

Zan Lynx
Hi thanks for your answer. I delete v because it is allocated on the heap , into a function of the main UI thread, wich is long dead at the end of the thread.
raph.amiard
A: 

Without seeing some of the 'stuff' happening in the locked regions, it is difficult to verify that your code would ever emerge from them. A couple of suggestions:

  1. It is possible that your thread is locking the critical section, then doing something which throws an exception, thereby exiting and failing to unlock. Make sure this does not happen by using scoped locking techniques.

  2. It is possible that one of the critical sections is simply not completing. Walk in with a debugger and verify expected behavior.

Adam