Problems with threads

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.
kshitij_ds
Filthy Rich wx Solver
Filthy Rich wx Solver
Posts: 205
Joined: Wed Jun 25, 2008 3:37 pm

Problems with threads

Post by kshitij_ds »

Hi All,
In my app, i am creating a thread to run some process. This thread is created with wxThreadHelper class and OnDialogActivate of a modal dialog created in the application.

Once the thread has done processing, EndModal(wxID_OK) is called and the dialog is destroyed. Now, my application has a menubar to launch this dialog. After clicking and successfully terminating the dialog 10-15 times my app crashes with following in GDB:

GThread-ERROR **: file /build/buildd/glib2.0-2.16.6/gthread/gthread-posix.c: line 367 (g_thread_create_posix_impl): error 'Cannot allocate memory' during 'pthread_create'
aborting...

When i put Debug logs in my code it looks like there was thread creation error:
if(wxThreadHelper::Create()==wxTHREAD_NO_ERROR)

This condition returns false.


Please help me as to what is wrong in this...
rodrigod
I live to help wx-kind
I live to help wx-kind
Posts: 172
Joined: Thu Jun 26, 2008 8:50 pm

Post by rodrigod »

Are you deleting all the objects you create inside the thread? perhaps you are creating the objects but never deallocating, after some times the memmory allocated gets full.
kshitij_ds
Filthy Rich wx Solver
Filthy Rich wx Solver
Posts: 205
Joined: Wed Jun 25, 2008 3:37 pm

Post by kshitij_ds »

Yeah, i am deleting all objects but still getting same error.
What's surprising to me is that there are no issues on Windows.
This is observed only under GTK+ and i have wx2.8.10.
kshitij_ds
Filthy Rich wx Solver
Filthy Rich wx Solver
Posts: 205
Joined: Wed Jun 25, 2008 3:37 pm

Post by kshitij_ds »

Ok I guess i have identified my issue and here it is with further details:

I have my thread class defined as
MyThread:public wxThreadHelper.
In my another dialog init code, a new object of MyThread is created as:
MyThread *thread = new MyThread;

In the constructor of MyThread, i create one object for another class and two other (one of wxMutex and wxCondition).

In ~MyThread Destructor, i am deleting all the above objects created in the constructor. When i debug through the code and when i am in the destructor, i notice that even after delete is called on all objects, memory associated with them is not released :( .
Additionally, in the destructor of my custom dialo, i delete thread object. However, even that is not released and there are no errors until memory is full and no more threads can be created!.
User avatar
doublemax
Moderator
Moderator
Posts: 19160
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Post by doublemax »

post some real code. If you describe something in words, you usually only describe what you believe to have programmed.

Additionally, wxThreadHelper is meant to be a mix-in class. If you just derive from it, you could just derive from wxThread instead.
Use the source, Luke!
kshitij_ds
Filthy Rich wx Solver
Filthy Rich wx Solver
Posts: 205
Joined: Wed Jun 25, 2008 3:37 pm

Post by kshitij_ds »

ok here is my code

Code: Select all

//This function is in my dialog that is launched on menu event. (File->Start Thread)

void MyDialog::InitMyThread()
{

  MyThread::myobj = myClass; //here myClass is someother class in my application
  MyThread::arrayList = list;//arrayList and list are wxArrayPtrVoid
  MyThread::myappObj = this;
  MyThread::boolVar = false;
  thread = new MyThread;
  thread->Run();

}
Now, let's look inside My Thread

Code: Select all

MyThread::MyThread(): wxThreadHelper()
{
  anotherClass = new anotherClass();//anotherClass is declared private in MyThread.h
  m_mutex = new wxMutex();
  m_condition = new wxCondition(*m_mutex);
}
The Thread is now run hence let's look at Entry Method:

Code: Select all

void* MacThread::Entry()
{
   EvtData evtData(m_mutex, m_condition);
   wxCommandEvent evt(wxEVT_COMMAND_BUTTON_CLICKED , ID_MYID);
   evt.SetClientData((void *) &evtData);
   ::wxPostEvent(myappObj,evt); 
   m_condition->Wait();
  return NULL;
}
In the above function, EvtData is another class that Locks the mutex in the constructor and unlocks it in the desctuctor (~EvtData). Event is posted to the main thread and Wait() method waits on the condition.

Once the event is processed this thread is signaled.
Let's look at the destructor:

Code: Select all

MacThread::~MacThread()
{
   delete anotherClass;
   delete m_condition;
   delete m_mutex;

}
That's all i have in my application. Even if I call delete memory is not released.[/code]
User avatar
doublemax
Moderator
Moderator
Posts: 19160
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Post by doublemax »

i assume MyThread and MacThread are the same, you just forgot to rename one of them?

Code: Select all

  MyThread::myobj = myClass; //here myClass is someother class in my application
  MyThread::arrayList = list;//arrayList and list are wxArrayPtrVoid
  MyThread::myappObj = this;
  MyThread::boolVar = false;
are these really static variables? why?

Code: Select all

thread = new MyThread;
thread->Run(); 
wxThreadHelper doesn't have a Run() method? If you edit your code to make it easier to understand, please don't make a guessing game out of it.

Code: Select all

   EvtData evtData(m_mutex, m_condition);
   wxCommandEvent evt(wxEVT_COMMAND_BUTTON_CLICKED , ID_MYID);
   evt.SetClientData((void *) &evtData);
   ::wxPostEvent(myappObj,evt);
   m_condition->Wait();
  return NULL; 
that's wrong, the pointer to evtData will be invalid by the time it's processed.

I assume there is some processing part missing? A thread that just sends a message is not very useful.
Use the source, Luke!
kshitij_ds
Filthy Rich wx Solver
Filthy Rich wx Solver
Posts: 205
Joined: Wed Jun 25, 2008 3:37 pm

Post by kshitij_ds »

Yes, they are static variables as myappObj needs to be shared between threads and so for other variables.

Also MacThread = MyThread;

I missed my Run method here it is:

Code: Select all

void MyThread::Run()
{
   if(wxThreadHelper::Create()==wxTHREAD_NO_ERROR)
   {// create thread
    GetThread()->Run();
   }
}
Well as far as processing is concerned, I have similar events one after the other.
I understand that the EvtData will be invalid by the time event is processed and hence I am waiting on the event to be processed. Like i said this thread (MyThread) will keep on waiting for the event to be processed.
Once the event is processed, wxConfition will be signaled and MyThread will resume to send out next event.
User avatar
doublemax
Moderator
Moderator
Posts: 19160
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Post by doublemax »

that's a little weird way of doing things, but nevertheless i don't see an obvious memory leak.

Code: Select all

thread = new MyThread;
thread->Run();  
where does thread get destroyed? Did you confirm that the thread dtor is actually executed?
Use the source, Luke!
kshitij_ds
Filthy Rich wx Solver
Filthy Rich wx Solver
Posts: 205
Joined: Wed Jun 25, 2008 3:37 pm

Post by kshitij_ds »

Yes i did verify that. thread gets deleted in my Dialog Destructor.
Like i said a modal dialog is launched when one cliks on App menu.
User avatar
doublemax
Moderator
Moderator
Posts: 19160
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Post by doublemax »

http://docs.wxwidgets.org/stable/wx_wxt ... l#wxthread
You shouldn't hurry to create all the threads joinable, however, because this has a disadvantage as well: you must Wait() for a joinable thread or the system resources used by it will never be freed, [...]
wxThreadHelper internally creates a joinable thread, so i guess this is somehow the reason for your error.

Try calling Wait() on the thread before destroying it.
Use the source, Luke!
kshitij_ds
Filthy Rich wx Solver
Filthy Rich wx Solver
Posts: 205
Joined: Wed Jun 25, 2008 3:37 pm

Post by kshitij_ds »

Calling Wait() does help somewhat but not entirely. I used Top to check the memory usage.
When i trigger my thread repeatedly, initially with "Wait()" not specified, the memory usage goes up like 40KB/s.
Including Wait() this rate reduces to 1/4th.
So, now the out of memory error is delayed..
User avatar
doublemax
Moderator
Moderator
Posts: 19160
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Post by doublemax »

i have no more ideas. I'd start commenting out parts of the code now until you can isolate the problem.
Use the source, Luke!
kshitij_ds
Filthy Rich wx Solver
Filthy Rich wx Solver
Posts: 205
Joined: Wed Jun 25, 2008 3:37 pm

Post by kshitij_ds »

one more question - I have a button in my dialog to terminate a thread, when i click it I call Delete() on thread.
However, the application hangs and never returns.
What is the proper way of terminating the thread then?
User avatar
doublemax
Moderator
Moderator
Posts: 19160
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Post by doublemax »

Delete() only works when your thread runs in a loop and calls TestDestroy() frequently.

If the thread waits for a condition like in your case, you can have to use wxThread::Kill()
http://docs.wxwidgets.org/stable/wx_wxt ... threadkill
Use the source, Luke!
Post Reply