Hello, I'm sorry for my absence from my original thread here:
viewtopic.php?f=2&t=87934
I stopped using VLC back then, but recently, as I was working on a project of my own and taking care of thread safety, I had an epiphany regarding this issue. Sadly, I didn't had the click, when I posted my last comment on that thread, but I think I have the answer now.
As you might have noticed, on that last reply of mine. I identified the fact that it's freezing after a call to GetMessage.
All this put together can only mean one thing, it's a deadlock. I'm not familiar with the code of VLC, so here's a simplified scenario of what I think it's going on, assuming you're using recursive mutexes:
void UIClass::doSomething()
{
lock_mutex();
SendMessage(WM_SOMETHING); // Or a call to something that will do a SendMessage
unlock_mutex();
}
void UIClass::OnWMSomething()
{
}
void UIClass::OnWMSomething2()
{
lock_mutex();
// something
unlock_mutex();
}
void RandomThread::ScrewUp()
{
UiThread->doSomething();
}
If you were to do SendMessage(WM_SOMETHING2); from doSomething() it is pretty clear how the code would fail. Giving the age of the project, I think that bug would have been found at the development stage, due to it's constant and certain generation of deadlocks. So I think you're actually doing SendMessage(WM_SOMETHING); - no mutex locks in its handler, but that doesn't prevent it from being wrong.
WM_SOMETHING could actually be any window message.
once ScrewUp() is called the following things will happen:
1) the mutex in question will get locked for the current RandomThread, inside UIClass::doSomething()
2) SendMessage will send WM_SOMETHING message and will wait for it to finish processing
3) OnWMSomething() will run on the UI Thread.
4) OnWMSomething() will return
5) the mutex will get unlocked inside UIClass::doSomething()
Q: Why is it wrong?
A: Because you're sending messages from inside a critical section.
Q: How can this cause the freeze?
A:
- Consider that at that point, the conditions are just right for messages to be sent to the message loop, outside of the RandomThread.
- Now consider that one of those messages gets handled between step 1 and step 2 AND that the message handler is locking the mutex.
- The result is that the message handler starts waiting for UIClass::doSomething() to finish, just before UIClass::doSomething() sends the non important message to the message loop and starts waiting for it. Message that will never get processed, because the message loop is stuck processing the previous message.
Example of non related message handler that can cause the freeze:
void UIClass::OnUnrelatedMessage()
{
lock_mutex();
// do nothing
unlock_mutex();
}
This IS assuming you're using recursive mutexes. If you are not using recursive mutexes, the deadlock could happen even on the same thread.
Solution:
Find all mutex references in your project and make sure you're not wrapping any message sending routines inside the critical sections. The message loop is already assuring thread safety so you can send messages outside of critical sections.
A proper rewrite of the doSomething method would look like this:
void doSomething()
{
lock_mutex();
int x = someSensitiveArray[10]; // Only wrap data access inside critical sections, or calls that strictly follow the OOP hierarchy
unlock_mutex();
SendMessage(WM_SOMETHING, x);
}
I hope this helps,
Thanks