Problem with wxThread::Wait - hangs console App Topic is solved

If you are using the main C++ distribution of wxWidgets, Feel free to ask any question related to wxWidgets development here. This means questions regarding to C++ and wxWidgets, not compile problems.
Post Reply
djenyc
Earned a small fee
Earned a small fee
Posts: 10
Joined: Fri Aug 18, 2006 5:02 pm

Problem with wxThread::Wait - hangs console App

Post by djenyc »

I'm trying to use wxThread in a cross platform Windows\Linux Embedded console app and after my thread finished processing wxThread::Entry, I try to call wxThread::Wait() before deleting the thread. That function hangs application, and CPU utilization goes to 100%. I traced the problem to this function:

wxThreadError
wxThreadInternal::WaitForTerminate(wxCriticalSection& cs,
wxThread::ExitCode *pRc,
wxThread *threadToDelete)

It get's stuck in the infinite loop

// we can't just wait for the thread to terminate because it might be
// calling some GUI functions and so it will never terminate before we
// process the Windows messages that result from these functions
// (note that even in console applications we might have to process
// messages if we use wxExecute() or timers or ...)
DWORD result wxDUMMY_INITIALIZE(0);
do
{
if ( wxThread::IsMain() )
{
// give the thread we're waiting for chance to do the GUI call
// it might be in
if ( (gs_nWaitingForGui > 0) && wxGuiOwnedByMainThread() )
{
wxMutexGuiLeave();
}
}

#if !defined(QS_ALLPOSTMESSAGE)
#define QS_ALLPOSTMESSAGE 0
#endif

result = ::MsgWaitForMultipleObjects
(
1, // number of objects to wait for
&m_hThread, // the objects
false, // don't wait for all objects
INFINITE, // no timeout
QS_ALLINPUT|QS_ALLPOSTMESSAGE // return as soon as there are any events
);

switch ( result )
{
case 0xFFFFFFFF:
// error
wxLogSysError(_("Can not wait for thread termination"));
Kill();
return wxTHREAD_KILLED;

case WAIT_OBJECT_0:
// thread we're waiting for terminated
break;

case WAIT_OBJECT_0 + 1:
// new message arrived, process it -- but only if we're the
// main thread as we don't support processing messages in
// the other ones
//
// NB: we still must include QS_ALLINPUT even when waiting
// in a secondary thread because if it had created some
// window somehow (possible not even using wxWidgets)
// the system might dead lock then
if ( wxThread::IsMain() )
{
// it looks that sometimes WAIT_OBJECT_0 + 1 is
// returned but there are no messages in the thread
// queue -- prevent DoMessageFromThreadWait() from
// blocking inside ::GetMessage() forever in this case
::PostMessage(NULL, WM_NULL, 0, 0);

wxAppTraits *traits = wxTheApp ? wxTheApp->GetTraits()
: NULL;

if ( traits && !traits->DoMessageFromThreadWait() )
{
// WM_QUIT received: kill the thread
Kill();

return wxTHREAD_KILLED;
}
}
break;

default:
wxFAIL_MSG(wxT("unexpected result of MsgWaitForMultipleObject"));
}
} while ( result != WAIT_OBJECT_0 );



It keeps hitting case WAIT_OBJECT_0 + 1

Is this a bug? How do I work around it. My thread is done, but the documentation says to call Wait before I delete it. Thanks
djenyc
Earned a small fee
Earned a small fee
Posts: 10
Joined: Fri Aug 18, 2006 5:02 pm

Something is odd with Visual Studio 2005 Debugger

Post by djenyc »

I remebered trying wxThread in a Console Sample App that came with wxWidgets and it worked fine. So I went back and ran it and found, that it runs fine as long as I don't have any breakpoints set in VS2005. If I have a breakpoint somewhere (doesn't have to be in the threading section), it could be even before thread get's created, when wxThread::Wait will hit a have a problem (infinite loop). Anybody seen it before? I love VS2005 debugger :)) so I'd rather make it work.

Thanks
rve
Earned a small fee
Earned a small fee
Posts: 11
Joined: Wed Nov 08, 2006 9:28 am
Location: Alphen aan den Rijn, Netherlands

Re: Problem with wxThread::Wait - hangs console App

Post by rve »

djenyc wrote: My thread is done, but the documentation says to call Wait before I delete it. Thanks
Not sure if its related to your problem but the documentation is incorrect. You do not have to Wait() for a thread. I also had (different) problems with it. See:

http://forums.wxwidgets.org/viewtopic.php?t=10873
Peer Sommerlund
Knows some wx things
Knows some wx things
Posts: 43
Joined: Tue Jun 13, 2006 7:21 am
Location: Denmark
Contact:

Post by Peer Sommerlund »

Could you post
1) the content of wxThread::Entry() -- or just the important parts
2) the content of the function that waits & deletes the thread
3) the content of the function that creates & runs your thread
4) a descriptoin of your program, what does it do, how many threads are it using.

Regards
djenyc
Earned a small fee
Earned a small fee
Posts: 10
Joined: Fri Aug 18, 2006 5:02 pm

Post by djenyc »

Peer Sommerlund, I'm wrigting an application that uses CTB Serial Port library. My program is suppose to collect data from multiple serial devices (sensors, receivers) and perform some processing on it, then save it on disk and forward it over TCP/IP to a server. For the purpose troubleshooting wxWidgets library I am trying to get a very simple program to work. Here is it's entire source code (just a few lines :) ):

#include "wx/app.h"
#include "wx/utils.h"
#include "wx/thread.h"

class CMonitorComm: public wxThread
{
public:
CMonitorComm(): wxThread(wxTHREAD_JOINABLE){;};
virtual void *Entry(){return 0;}
};

int main(int argc,char* argv[])
{
wxApp::CheckBuildOptions(WX_BUILD_OPTIONS_SIGNATURE, "program");
wxInitializer initializer;
if (!initializer )return 3;
CMonitorComm* m_psermonThread=new CMonitorComm();
if (m_psermonThread->Create() != wxTHREAD_NO_ERROR) return 3;
m_psermonThread->Run();
wxSleep(10);
m_psermonThread->Wait();
delete m_psermonThread;
return 0;
}

Entry function exits fine. The program runs fine and terminates fine if I don't set and hit any breakpoints in Visual Studio 2005. It also runs fine outside of Visual Studio. I only have a problem I hit a breakpoint in the debugger. wxThread Wait function calls wxThreadInternal::WaitForTerminate function and the later get's suck.

WaitForTerminate starts processing message queue and goes in to an infinite loop. I haven't done gui, may it's a bug that only affects console apps?
djenyc
Earned a small fee
Earned a small fee
Posts: 10
Joined: Fri Aug 18, 2006 5:02 pm

Post by djenyc »

rve, I took on your suggestion and omited a call to wxThread::Wait before deleting the thread object. This solved my problem with debugger... Hm, looks like the manual needs an update. Can anybody comment if ommiting call to Wait before deleting thread object is the way to go about it, or can this cause problems down the road?
Peer Sommerlund
Knows some wx things
Knows some wx things
Posts: 43
Joined: Tue Jun 13, 2006 7:21 am
Location: Denmark
Contact:

Post by Peer Sommerlund »

So, everything works fine -- except when you are debugging inside Visual Studio. The code looks fine to me. Have you considered debugging it using log-files instead of a debugger? :wink: This is what I do. I often find that too many things happen that is not reproducable in a debugger. Also, race conditions are easier to understand when using log files.

I'm not an expert, but if you don't wxThread::Wait() for a joinable thread, I assume this would cause hanging threads. The code for wxThread::~wxThread() in wxMSW calls ::CloseHandle(), which does not terminate the thread. I suppose the debugger cleans up for you in this case.
djenyc
Earned a small fee
Earned a small fee
Posts: 10
Joined: Fri Aug 18, 2006 5:02 pm

Post by djenyc »

>Have you considered debugging it using log-files instead of a debugger?

Ah, shure logs work, but you gotta know before hand what variables you are interested in. Debugger is more interactive.

I did debugging in threaded apps in VS2005 before, while using MFC AfxStartThread and it worked fine, so that looks like a bug in wx.

Anybody got personal favorites for cross-platform threads libary? May be boost? though I can't figure how to get it to cross-compile for embedded linux.
rve
Earned a small fee
Earned a small fee
Posts: 11
Joined: Wed Nov 08, 2006 9:28 am
Location: Alphen aan den Rijn, Netherlands

Post by rve »

djenyc wrote:rve, I took on your suggestion and omited a call to wxThread::Wait before deleting the thread object. This solved my problem with debugger... Hm, looks like the manual needs an update. Can anybody comment if ommiting call to Wait before deleting thread object is the way to go about it, or can this cause problems down the road?
The thread should be ended before deleting the object. You can use Wait() to wait until the thread ends automatically or use Delete() to signal the thread to stop and wait until it is stopped. So yes, you should have a Wait()/Delete()/Kill() before deleting the thread object.
Post Reply