How to manage the deletion and recreation of a main frame and a working thread in a multithreaded application in wxWidgets - c++

Introduction
I am new to multithreading. I have an created a GUI application in c++ on windows 10 using wxWidgets. A worker thread communicates in the background via sockets and appends events to some event handlers from the main thread (GUI); I have two available protocols for the communication, and I allow the user to choose among those at the beginning (before instantiating the thread). To append events, I have a few shared pointers on the event handlers; a bit like in this tutorial, where it keeps a pointer of the m_parent. To communicate with the working thread, I created a queue using a mutex and semaphore, also like in the tutorial. For now, everything works.
Now, I want to let the user change the protocol while the application runs. I have thus a menu with a related button. This button calls the following function (create_app()) that deletes the top window and the communication thread and recreates everything. That is where I have problems.
bool cApp::create_app() {
wxWindow* main_window = GetTopWindow();
// If there is already a window, delete everything before creation
if(main_window) {
//thread_communication->Wait(); // Should I wait for the thread to finish? I shouldn't
if (thread_communication->Delete() != wxTHREAD_NO_ERROR) { // Should I delete it since it should be destroyed when Entry is finished
std::cerr << "DELETE IMPOSSIBLE!" << std::endl;
return false;
}
if (main_window->Destroy() != wxTHREAD_NO_ERROR) { // Here I can't delete the window
std::cerr << "DELETE WINDOW IMPOSSIBLE!" << std::endl; // prints
return false;
}
SetTopWindow(NULL);
}
// Create everything
m_frame1 = new MainFrame(*this);
SetTopWindow(m_frame1);
m_frame1->Show();
std::vector<std::shared_ptr<wxEvtHandler>> evt_handlers;
m_frame1->get_handlers(evt_handlers);
// Construct the working thread with the evt handlers and the queue from the main window
thread_communication = std::unique_ptr<ThreadCom>(new ThreadCom(evt_handlers, m_frame1->get_queue());
wxThreadError err = thread_communication->Create();
...
err = thread_communication->Run();
...
return true;
}
bool cApp::OnInit() {
return create_app();
}
When the user click the related button, it calls this create_app function but before sends a task via the queue to the working thread with the highest priority (meaning it will be the next task achieved by it); afterwards, in the working thread, it exits after poping the task the while loop in Entry. Thus, the working thread should terminate there.
Problem
I have problem when deleting the thread and the application. I have memory leaks since, I guess, they share common material (pointers).
When I try to use Wait, I have first a assert !IsDetached. That is because I cannot wait for a detached thread. If I continue, the programm crashes (Access violation reading location) during the thread->Delete() call.
If I don't use Wait, the thread->Delete() call works fine. Afterwards, the program crashes at main_window->Destroy(); the return code is not ok thus it prints "DELETE WINDOW IMPOSSIBLE" with an Unhandled exception thrown: read access violation message.
So, how should I proceed? Should I implement destructors in the classes? How can I delete the thread and the app safely?
Thanks in advance for your help.

Related

C++ threads freeze program

I am currently working on a game in C++ which is supposed to use multithreading to handle bot instances.
The Bot class has a member function start(), which calls the bot's function walk() in a new thread. This is my attempt (in excerpts:)
void Bot::walk(Physics& physics)
{
// do stuff
std::cout << "call to walk() function" << std::endl;
}
void Bot::start(Physics& physics)
{
std::thread m_thread(&Bot::walk, this, std::ref(physics));
m_thread.join();
}
In another class which handles the initialization of the game, all bot instances are started like this: (m_bots is a vector of Bots)
void Level::start()
{
// Start all Bots
for(auto it: m_bots)
{
it->start(*m_physics);
}
}
On startup the game window opens as usual but then continues to freeze. The console output shows that the walk() function is called though.
What thread-specific catch am I missing?
I hope these excerpts cover all the relevant information. If this is not the case, please let me know!
Joining a thread blocks until the thread finishes. As a result, Bot::start won't return until the thread that it spawns finishes, so only one thread will run at a time.
Someone will probably tell you that the solution is to change join() to detach(). That's not really the solution, unless your design calls for a bunch of free-running threads; if you care about when they finish, join() is the way to do it, just not there.
One approach is to create an object of type std::vector<std::thread> and launch all of the thread with calls to Bot::start. After the threads are running you can join all the spawned threads.

Qt avoid warning QProcess: destroyed while process still running (Assistant)

I am running a Qt app that launches a process. (The Assistant, launched from the main app).
When I close the app, I get the warning
QProcess: Destroyed while process is still running.
How can I get rid of it ?
I saw this similar question and tried to kill... Nothing happened.
This question seems to say maybe I should add waitForFinished()... Help won't close when app does.
Help::Help():m_helpProcess(0) {}
Help::~Help()
{
if (m_helpProcess) {
m_helpProcess.waitForFinished(); // help stays open after app closes
m_helpProcess->kill(); // added with no effect
delete m_helpProcess;
}
}
bool Help::start()
{
if (!m_helpProcess)
process = new QProcess();
QStringList args;
args << QLatin1String("-collectionFile")
<< QLatin1String("mycollection.qhc");
process->start(QLatin1String("Assistant.app"), args);
if (!process->waitForStarted())
return;
}
It should be sufficient to rewrite the destructor using close():
Closes all communication with the process and kills it. After calling this function, QProcess will no longer emit readyRead(), and data can no longer be read or written.
Help::~Help()
{
if (m_helpProcess) {
// m_helpProcess->waitForFinished(); // help stays open after app closes
m_helpProcess->close(); // close channels
delete m_helpProcess; // destructor actually kills the process
}
}

Indy10 TCP Server Freezing

I using Indy with C++ Builder XE3. It's perfect system but i have some problems. IdTCPServer works really good but when i have some connections on him and i want to stop server then my application freezed. I try to tell how i do it step by step:
1) Starting application (and server listening)
2) wait for new connections (or simulate it, no difference)
3) when we have 10-15 connections - then try to stop server listening.
4) when code came to IdTCPServer1->Active = false - application will be frozen
i made little video. Maybe it explain situation much better. http://www.youtube.com/watch?v=BNgTxYbLx8g
And here my code:
OnConnect:
EnterCriticalSection(&CritLock);
++ActiveConnections;
SetActiveConnections(ActiveConnections);
LeaveCriticalSection(&CritLock);
OnDisconnect:
EnterCriticalSection(&CritLock);
--ActiveConnections;
SetActiveConnections(ActiveConnections);
LeaveCriticalSection(&CritLock);
StopServer Code:
void TForm1::StopServer()
{
TList *list = IdTCPServer1->Contexts->LockList();
try
{
for(int i = 0; i < list->Count; ++i)
{
TIdContext *AContext = reinterpret_cast<TIdContext*>(list->Items[i]);
try
{
if (AContext->Connection->Connected())
{
AContext->Connection->IOHandler->InputBuffer->Clear();
AContext->Connection->IOHandler->WriteBufferCancel();
AContext->Connection->IOHandler->WriteBufferClear();
AContext->Connection->IOHandler->WriteBufferClose();
AContext->Connection->IOHandler->CloseGracefully();
AContext->Connection->Disconnect();
}
}
catch (const Exception &e)
{
}
}
}
__finally
{
IdTCPServer1->Contexts->UnlockList();
}
IdTCPServer1->Contexts->Clear();
//IdTCPServer1->StopListening();
IdTCPServer1->Active = false;
}
Thanks for advise!
You need to get rid of all your StopServer() code except for the very last line. When TIdTCPServer is deactivated, it performs all necessary cleanups for you. DO NOT DO IT YOURSELF (especially since you are doing it wrong anyway).
void TForm1::StopServer()
{
IdTCPServer1->Active = false;
}
Now, with just that code, if your app is still freezing, then that means you are deadlocking the main thread. That happens if you call StopServer() in the context of the main thread and one of two things are happening in your server code:
one of your TIdTCPServer event handlers performs a synchronized operation to the main thread (either via TIdSync or TThread::Synchronize()).
one of your TIdTCPServer event handlers swallows Indy exceptions and does not allow TIdTCPServer to terminate one or more client threads correctly when needed.
Internally, the TIdTCPServer::Active property setter closes all active sockets and waits for their respective threads to fully terminate, blocking the calling thread until the property setter exits. If yoou are deactivating the server in the main thread and one of the server threads performs a sync that the main thread cannot process, or otherwise does not terminate correctly when it should be, that will block the server deactivation from exiting and thus deadlock the main thread.
So make sure that:
you are not performing sync operations to the main thread while the server is being deactivated by the main thread. If you must sync, then deactivate the server in a worker thread instead so the main thread is not blocked anymore.
your event handlers are not swallowing any Indy EIdException-derived exceptions in try/catch blocks. If you catch such an exception, re-throw it when you are finshed using it. Let TIdTCPServer handle any Indy exceptions so it can perform internal cleanups as needed.
Lastly, on a side note, you do not need to keep track of connections manually. TIdTCPServer already does that for you in the Contexts property. If you need to know how many clients are currently connected at any moment, simply Lock() the Contexts list, read its Count property (or do anything else you need to do with the clients), and then Unlock() the list.

How to lock code execution in iOS application

Problem Description
I have a function StdString ShowLockScreen() in this function I call activateViewController function which shows some UI where user must enter PIN, just after calling activateViewController function I want to lock all processes until user will enter his PIN and press OK button on opened UI. Below you can see code which I try
Source code in iOS
StdString ShowLockScreen()
{
// Create a lock.
NSLock* theLock = [[NSLock alloc] init];
// Create a UI in which user must enter his PIN.
PinLockController* controller = [[PinLockController alloc] initWithStyle:PinLockTypeSet];
// Set delegate.
controller.delegate = m_Context;
// !!! Here I show a UI and just after that I lock my lock in order code stop executing there.
[controller activateViewController:nil];
#synchronized(theLock) {
[theLock lock];
}
NSLog(#"User in UI unlock the lock");
}
I want that my code stops then I call [theLock lock]; and after I will call [theLock unlock]; from my UI and code will continue executing. But it doesn't work in my case.
Source code in Android
I have write similar application in Android and here is code. I want to write same in iOS but I can;t find solution
Intent intent = new Intent(mCtx, SoftPinActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
SharedObject lock = new SharedObject("");
int lockId = SharedObject.acquireLockId(lock);
Logger.i(TAG, "lockId = " + lockId);
intent.putExtra(SharedObject.LOCK_ID, lockId);
intent.putExtra(SoftPinActivity.UI_ID, style);
synchronized (lock) {
mCtx.startActivity(intent);
try {
Logger.i(TAG, "lock.wait()...");
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
Logger.i(TAG, "InterruptedException");
}
}
Logger.i(TAG, "lock.wait()...done");
SharedObject.releaseLockId(lockId);
String pin = lock.object();
Researches
I think I must use
NSCondition* condLock = [[NSCondition alloc] init];
[condLock wait];
and
[condLock signal];
but how to use this in my code ?
Answer to problem
You can lock threads using NSLock, but in your situation, this doesn't seem to be applicable. The reason being is that locking is primarily used to provide thread safety when data is accessed from multiple threads. What you're asking for is a domain level lock, which prevents the user from using the application unless they've typed in their PIN. These two concepts share the word "lock", but they're entirely different in their implementation. If you were to use NSLock and its related counterparts, you're forcing your implementation into separate threads purely to block user interaction, and risk complicating your project and pains in debugging (deadlocks much?).
Suggested solution
As the concept is a domain level locking mechanism, I suggest we keep it this way for its implementation. If you want it to be analogous to Android, then you'd need to create your own concept of a 'SharedObject' that everything else queries. If this object were to say "The user hasn't unlocked the application", then nothing will process. This keeps you away from manually managing threads, and frees threads up for when you really need them most (asynchronous processing for example).
To implement this object, lets call it a UserContext, which is available as a singleton. How to implement this sharedInstance can be seen here.
Once you have that, then you can add various properties to it that are global throughout the application (and by the suggestion of the name, has all global properties that belong to a particular user). One of these properties is whether the user has the app locked or not:
[[UserContext sharedInstance] isLocked] // Returns BOOL
Using this throughout your application, you can then control (at the domain concept level), whether a method can compute something or not (naturally, you'll need to make UserContext thread safe, as it could be queried anywhere at any time). It would make it clear to the developer reading the code, that a certain method can not do anything unless the user has unlocked the app. To stop
Side notes
I want that my code stops then I call [theLock lock]; and after I will call [theLock unlock]; from my UI and code will continue executing.
Do not, under any circumstances, lock the UI thread. In a published app, the watchdog will kill your app, and it will effectively crash.
ViTo, as much I concerned with the NSLock, we use it in the case of multi-threading in which we lock a particular thread and force that upto that not unlock, none other thread become active or to do his required task.
So, may be what we can do that first of all we start all of your processes in the terms of thread and at that point when you try to open your UI we call 'lock' and when user pressed the button after inputting the text-box then we call 'unlock'.
But, for this we've to sure that this thread has high priority.
That's what I'm thinking right now, but really try this with my sample code and will update you accordingly.
Check that part of code:
+(void)aMethod:(id)param{
int x;
for(x=0;x<50;++x)
{enter code here
[lock lock];
printf("Object Thread says x is %i\n",x);
usleep(1);
[lock unlock];
}
}
- (void)viewDidLoad
{
int x;
lock = [[NSLock alloc] init];
[NSThread detachNewThreadSelector:#selector(aMethod:) toTarget:[MViewController class] withObject:nil];
for(x=0;x<50;++x)
{
[lock lock];
printf("Main thread says x is %i\n",x);
usleep(10000);
printf("Main thread lets go %i\n",x);
[lock unlock];
usleep(100);
}
printf("Now getting the process");
[super viewDidLoad];
}
Check the log you'll get what you want.
Hope, it's what you need. For any concern, shout-over me.
Okay I found solution to this issue, below you can see implemented function and line by line description.
StdString ShowLockScreen()
{
// Create NSCondition lock object.
NSCondition* conditionLock = [[NSCondition alloc] init];
// Here I create my UI which must ask user to enter PIN.
PinLockController* controller = [[PinLockController alloc] initWithStyle:PinLockTypeSet];
controller.delegate = m_Context;
// Here I lock the thread but not main thread (this is very important) I start
// ShowLockScreen function in new thread and lock it.
[conditionLock lock];
dispatch_sync(dispatch_get_main_queue(), ^{
// I call function which shows my UI in main thread as UI can be shown
// only in MAIN THREAD. (This is important too.)
[controller ShowLockController:conditionLock];
});
// Then I set lock to wait, how you can see I pass conditionLock as an
// argument to ShowLockController function in that function when user
// enter his PIN and press okay button I call [conditionLock signal];
// and my code code here after wait and continue executing.
[conditionLock wait];
NSLog(#"Come here then I call [conditionLock signal]!!!")
}

Terminating thread

I've a dialog displaying progress bar + some other data, and I also have a cancel button on this dialog. While this dialog is displayed there is potentially heavy computation going on, which is show on progress bar. This computation is started from withing this dialog code so I have:
Counting_Progress_Dialog::Counting_Progress_Dialog(QWidget *parent) :
QDialog(parent)
{
setupUi(this);
thread_ = new Threaded;//THIS IS THE THREAD IN WHICH COMPUTATION IS BEING PERFORMED
connect(thread_,SIGNAL(counter_value(int)),this,SLOT(update_progress_bar(int)));
connect(this,SIGNAL(rejected()),thread_,SLOT(terminate()),Qt::QueuedConnection);//
HERE I'M CONNECTING REJECTED ON DIALOG TO TERMINATE ON THREAD
}
void Counting_Progress_Dialog::start()
{
thread_->start(QThread::LowestPriority);
}
and I do invoke this in part of the program:
void My_Class::dummy_()
{
auto old_priority = this->thread()->priority();
this->thread()->setPriority(QThread::HighestPriority);
Counting_Progress_Dialog progress;
progress.start();//this will start thread
progress.exec();//this will enter it's event loop
progress.wait();//this will wait until thread is finished
this->thread()->setPriority(QThread::NormalPriority);
}
But despite all this, when I press cancel on my dialog, the whole application freezes. What am I doing wrong? How to make it behave correctly?
UPDATED:
void Counting_Progress_Dialog::wait()
{
thread_->wait();
}
I see that you are connecting using 2 different strategies. But if thread_ and this(counting dialog) are really within two separated threads then the connection will always be Qt::QueuedConnection. Well that's not the issue.
progress.exec();//this will enter it's event loop
Calling exec() suspend the execution of dummy_() until the dialog have to return. And when the dialog return your thread is terminated. So I don't see the purpose of
progress.wait();//this will wait until thread is finished
By the way which function is that? the only one I know is Qthread::wait(). I am pretty confident the issue is here...
edit:
progress.wait() is not the issue... But it is possible that the events sent by the thread are causing trouble in some way. Use the debugger or some qDebug() to see if update_progress_bar is called after you push cancel.