|
|
Home » U++ Library support » U++ MT-multithreading and servers » DnD hangs in MT Refresh()ing
DnD hangs in MT Refresh()ing [message #24717] |
Thu, 28 January 2010 16:58 |
|
kohait00
Messages: 939 Registered: July 2009 Location: Germany
|
Experienced Contributor |
|
|
hi people
i am currently struggeling with a GUI / MT behaviour of U++ Ctrl stuff. i attached a Test environment, a modified CoWork. it does the following.
it fires up some CoWork Threads/Jobs, which simply do a
while(dorun)
{
Refresh(); //which internally does GuiLock somewhere, no problem, THEORETICALLY
Sleep(1);
}
and the Paint paints something dynamic, to see if it still is running something.
there is also a TreeCtrl, filled in same way as TreCtrlDnd example,
PROBLEM/BUG: start DnD some elemen of TreeCtrl without releasing it, soon the running Threads will freeze and not perform any refresh anymore. if minimizing and maximizing again, it starts to work, having performed its work; >> but until than it hangs !!!
do i misunderstand somehow the concept of GuiLock and MT things here? it seems to me that its kind of a deadlock with maybe one of the sPteLock, StaticMutex or GlobalMutex or the like..any guess?
BACKGROUND:
i am working on a application that uses I/O Completion Ports Queue (Win32 specific) and a CoWork threads pool, which performs he completion tasks. i receive periodic, frequent data, which i directly push throough to controls, which should be ok, since they somewhere invoke Refresh() which will do a GuiLock. so tey should be ok. and it works, that far. as soon as i start to DnD things, while a control, which is beeing driven directly by the completion threads for refreshment, is open, the whole thing hangs/freezes without mercy. so i tried to make a simple test. which almost does the same, but my own application is not recoverable. if i stop the debuger it points me to some point in ntdll, which smells of Mutex or Critical Section or what.
-
Attachment: CoWork.rar
(Size: 7.33KB, Downloaded 337 times)
|
|
|
|
Re: DnD hangs in MT Refresh()ing [message #24735 is a reply to message #24734] |
Fri, 29 January 2010 00:22 |
|
kohait00
Messages: 939 Registered: July 2009 Location: Germany
|
Experienced Contributor |
|
|
2 cores here, one needs to playe something with the element, dragging it in the tree without release, it does not hang immediately. slows down, later it hangs. sometimes it hangs as soon as released.
this is really weired. i was trying to investigate what kind of mutexes are involved. there is the NonMainMutex, sGLock, and also one needs to consider the semaphore wait in ICall interface. maybe the threads just inject themselves at a point when calling Refresh and locking GuiLock, not beeing able to continue doe to wait for semaphore of ICall, which is released after completion of ICall in main thread, which in turn cant complete the call, cause the DragAndDrop thing is doing a release LeaveGMutexAll, performing the draganddrop and not beeing able to EnterGMutex(level) anymore, cause one of the worker threads has started something. but there you also do a leave/wait for semaphore/enter, so GuiLock is not aquired there. man, no idea
i'll watch on that, thanks
BTW: have you spent any thoughts on integrating the high performance stuff of completion ports for sockets/files, both on win32 and linux (real kernel aio, not the posix indermediate rubish)?
|
|
|
|
Re: DnD hangs in MT Refresh()ing [message #24743 is a reply to message #24741] |
Fri, 29 January 2010 09:32 |
|
kohait00
Messages: 939 Registered: July 2009 Location: Germany
|
Experienced Contributor |
|
|
got some investigation on it (on MY app, not the CoWorker, but should be similar, i checked it, it behaves like that):
the problem even occurs with only 1 worker thread
(replacing the whole CoWork co with a Thread th and Run() the DoRefresh cb there)
DoCall() in Win32Wnd.cpp:747 always returns true (because NonMain counter is up to 25), so the ProcessEvent(bool *quit) cant go on processing other stuff and do a repaint on gui or dispatch user events.
the sGLock is owned by GUI thread, GuiSleep is running and so releasing GUI mutex sGLock from time to time, so potential other threads in need of gui lock, should run right.
the NonMainLock is owned by a worker thread and is not released anymore, there comes the deadlock, but NOT with the gui mutex, for sure, maybe the semaphore.wait in ICall or Call interface.
What is the NonMainMutex actually for? i think that is more or less the problem..
any idea?
[Updated on: Fri, 29 January 2010 09:36] Report message to a moderator
|
|
|
Re: DnD hangs in MT Refresh()ing [message #24745 is a reply to message #24743] |
Fri, 29 January 2010 10:31 |
|
kohait00
Messages: 939 Registered: July 2009 Location: Germany
|
Experienced Contributor |
|
|
one more:
indeed, in CtrlMT.cpp
void Ctrl::ICall(Callback cb)
is suffering a not release of semaphore due to an early CtrlCall.Clear in a DoCall somewhere in between, maybe from another thread??, so that the PerformCall cant be executed, which would release the semaphore...is there any other thread accessing DoCall?
a short log, sem1 is the ones from ICall, simpli with an id counter, sem2 is the ones from Call interfaces.
..
DoCall
Sem release, sem1 934 sem2 0
DoCall::CtrlCall clear sem1 934 sem2 0
SEM1 released 934
SEM1 wait 935
DoCall
Sem release, sem1 935 sem2 0
DoCall::CtrlCall clear sem1 935 sem2 0
SEM1 released 935
SEM1 wait 936
DoCall
Sem release, sem1 936 sem2 0
SEM1 released 936
DoCall::CtrlCall clear sem1 936 sem2 0
SEM1 wait 937
DoCall
DoCall::CtrlCall clear sem1 937 sem2 0
DoCall
DoCall::CtrlCall clear sem1 937 sem2 0
DoCall
DoCall::CtrlCall clear sem1 937 sem2 0
the CtrlMt.cpp used for that is the current one, from yesterday svn, so you can see where what is logged
#include "CtrlCore.h"
#define LLOG(x) // LOG(x)
NAMESPACE_UPP
#ifdef _MULTITHREADED
static int sem1 = 0;
static int sem2 = 0;
static int NonMain;
static StaticMutex NonMainLock;
void EnterGuiMutex()
{
Mutex & m = NonMainLock.Get();
LLOG("Thread " << IsMainThread() << " trying to lock");
bool nonmain = !IsMainThread();
if(nonmain)
NonMainLock.Enter();
EnterGMutex();
if(nonmain)
NonMain++;
LLOG("Thread " << IsMainThread() << " LOCK");
}
void LeaveGuiMutex()
{
Mutex & m = NonMainLock.Get();
LLOG("Thread " << IsMainThread() << " trying to unlock");
bool nonmain = !IsMainThread();
if(nonmain)
NonMain--;
LeaveGMutex();
if(nonmain)
NonMainLock.Leave();
LLOG("Thread " << IsMainThread() << " UNLOCK");
}
struct Ctrl::CallBox {
Semaphore sem;
Callback cb;
};
void Ctrl::PerformCall(Ctrl::CallBox *cbox)
{
cbox->cb();
LOG("Sem release, sem1 " << sem1 << " sem2 " << sem2);
cbox->sem.Release();
}
Callback Ctrl::CtrlCall;
void WakeUpGuiThread();
bool Ctrl::DoCall()
{
LOG("DoCall");
CtrlCall();
LOG("DoCall::CtrlCall clear sem1 " << sem1 << " sem2 " << sem2);
CtrlCall.Clear();
LLOG("--- DoCall, nonmain: " << NonMain);
int a = NonMain;
return NonMain;
}
void Ctrl::ICall(Callback cb)
{
LLOG("Ctrl::Call " << IsMainThread() << ", nonmain: " << NonMain);
if(IsMainThread())
cb();
else {
CallBox cbox;
cbox.cb = cb; ++sem1;
CtrlCall = callback1(PerformCall, &cbox);
int level = LeaveGMutexAll();
WakeUpGuiThread();
LLOG("Waiting for semaphore");
if(!Thread::IsShutdownThreads())
{
LOG("SEM1 wait " << sem1);
cbox.sem.Wait();
LOG("SEM1 released " << sem1);
}
EnterGMutex(level);
}
LLOG("-- Ctrl::Call " << IsMainThread());
}
void Ctrl::Call(Callback cb)
{
if(IsMainThread())
cb();
else {
CallBox cbox;
cbox.cb = cb; ++sem2;
UPP::PostCallback(callback1(PerformCall, &cbox));
int n = NonMain;
int nn = n;
NonMain = 0;
for(int i = 0; i < n; i++)
NonMainLock.Leave();
int level = LeaveGMutexAll();
WakeUpGuiThread();
if(!Thread::IsShutdownThreads())
{
LOG("SEM2 wait " << sem2);
cbox.sem.Wait();
LOG("SEM2 released " << sem2);
}
for(int i = 0; i < n; i++)
NonMainLock.Enter();
EnterGMutex(level);
NonMain = n;
}
}
#else
bool Ctrl::DoCall()
{
return false;
}
void Ctrl::ICall(Callback cb)
{
cb();
}
void Ctrl::Call(Callback cb)
{
cb();
}
#endif
void Ctrl::GuiSleep(int ms)
{
Call(callback1(&Ctrl::GuiSleep0, ms));
}
void Ctrl::WndDestroy()
{
ICall(callback(this, &Ctrl::WndDestroy0));
}
#ifdef PLATFORM_WIN32
void Ctrl::WndCreateCaret(const Rect& cr)
{
ICall(THISBACK1(WndCreateCaret0, cr));
}
#endif
void Ctrl::WndShow(bool b)
{
ICall(THISBACK1(WndShow0, b));
}
void Ctrl::WndUpdate()
{
ICall(THISBACK(WndUpdate0));
}
void Ctrl::SetWndForeground()
{
ICall(THISBACK(SetWndForeground0));
}
bool Ctrl::WndEnable(bool b)
{
ICall(THISBACK1(WndEnable0, &b));
return b;
}
bool Ctrl::SetWndFocus()
{
bool b;
ICall(THISBACK1(SetWndFocus0, &b));
return b;
}
void Ctrl::WndInvalidateRect(const Rect& r)
{
ICall(THISBACK1(WndInvalidateRect0, r));
}
void Ctrl::WndSetPos(const Rect& rect)
{
ICall(THISBACK1(WndSetPos0, rect));
}
void Ctrl::WndUpdate(const Rect& r)
{
ICall(THISBACK1(WndUpdate0r, r));
}
void Ctrl::WndScrollView(const Rect& r, int dx, int dy)
{
ICall(THISBACK3(WndScrollView0, r, dx, dy));
}
void Ctrl::EventLoop(Ctrl *ctrl)
{
Call(callback1(&Ctrl::EventLoop0, ctrl));
}
END_UPP_NAMESPACE
|
|
|
|
|
|
|
|
|
|
|
Re: DnD hangs in MT Refresh()ing [message #24757 is a reply to message #24717] |
Fri, 29 January 2010 13:08 |
|
kohait00
Messages: 939 Registered: July 2009 Location: Germany
|
Experienced Contributor |
|
|
GOOOD NEWS mirek...it works for me !! but not for the CoWork
i tested my software under pretty heavy conditions. my software does NOT hang. thanks a LOT!! that's driven me crazy a week now. i should have provided you the info that in deed, the worker threads perform a long enough task on the gui, just like you guessed. sorry for that. i think this will become a patch. are there any drawbacks on that? performance hits, deadlock potentials? (the more mutexes one uses
but the CoWork test has failed. it seems to have another problem in CoWork anyway, cause one can still click and see the title change the caption, so the message queue is runnning.
i could not grasp the exact error there, have you been able to reproduce the hang in the custom CoWork??
interestingly enough, when the test application "freezes", it seems only the worker threads freeze, as soon as you change the size of the window or minimize/maximize, it continues again.
just go on posting if you cant reproduce it. ill try it here.
[Updated on: Fri, 29 January 2010 13:13] Report message to a moderator
|
|
|
Re: DnD hangs in MT Refresh()ing [message #24758 is a reply to message #24757] |
Fri, 29 January 2010 13:21 |
|
mirek
Messages: 13985 Registered: November 2005
|
Ultimate Member |
|
|
kohait00 wrote on Fri, 29 January 2010 07:08 | GOOOD NEWS mirek...it works for me !! but not for the CoWork
i tested my software under pretty heavy conditions. my software does NOT hang. thanks a LOT!! that's driven me crazy a week now.
|
Glad to hear that. This stuff is really complicated...
Quote: |
i should have provided you the info that in deed, the worker threads perform a long enough task on the gui, just like you guessed. sorry for that. i think this will become a patch. are there any drawbacks on that? performance hits, deadlock potentials? (the more mutexes one uses
|
If there is any performance impact, it is negligible. And race conditions are bugs in any case! Incorrect code has to be fixed.
Quote: |
but the CoWork test has failed. it seems to have another problem in CoWork anyway, cause one can still click and see the title change the caption, so the message queue is runnning.
i could not grasp the exact error there, have you been able to reproduce the hang in the custom CoWork??
|
Unfortunately, no. Frankly, this use of CoWork is very weird, but I understand it is just testcase.
In any case, the exit strategy of this testcase is invalid - it freezes on close and rightfully so. But that is another issue, I guess...
Quote: |
interestingly enough, when the test application "freezes", it seems only the worker threads freeze, as soon as you change the size of the window or minimize/maximize, it continues again.
just go on posting if you cant reproduce it. ill try it here.
|
Yes, I cannot reproduce it...
Mirek
|
|
|
|
|
|
|
Goto Forum:
Current Time: Sun Jun 16 15:47:35 CEST 2024
Total time taken to generate the page: 0.01933 seconds
|
|
|