PDA

View Full Version : handling exceptions in Qt



sattu
28th January 2013, 11:11
Hi Everyone,

We are working on embedded linux platform. We use .wav files for our audio purpose. Recently due to some reason few wav files had got corrupted and when we were played them the application crashed giving the following exception:- "Floating point exception". Then when we replaced those wav files with new ones it again became fine.
My doubt is not exactly related to this exception but related to the crashing of application when such exceptions arise.
So can someone suggest us some effective means/ways to handle such exceptions which ultimately lead to crashing of the main application? :confused:



-Thanking everyone
Sattu

Santosh Reddy
28th January 2013, 11:43
Qt does not control the exceoptions in C/C++ code. Exceptions / traps / signals are just as in plain C/C++.

There are some compiler options to get such exception signals....Try googling "floating point exception", lot of stuff is there.

sattu
28th January 2013, 12:37
Try googling "floating point exception", lot of stuff is there.

Thanks but as I mentioned my doubt is not exactly related to this particular exception but how to prevent the crashing of my app once such exceptions arise. But again as you mentioned Qt doesn't deal with it as it comes from C++ code. So I guess I ultimately have to google :p

wysota
28th January 2013, 12:45
You can use signal() or sigaction() to install a handler for SIGFPE and SIGSEGV however be aware that when receiving such signal your application may be in an undefined state so the only thing you should do at this point is to gracefully quit the application. SIGFPE has nothing to do with C/C++ exceptions.

sattu
28th January 2013, 13:32
......... receiving such signal your application may be in an undefined state so the only thing you should do at this point is to gracefully quit the application

Thanks a lot Wysota. But what do you mean exactly by "application may be in an undefined state"? I mean can we atleast popup a message showing the reason of the crash to the end user and write the same to a log file before quitting the application?

wysota
28th January 2013, 14:18
But what do you mean exactly by "application may be in an undefined state"?
Applications are crashing not because people who implemented your operating system were malicious, but rather that when your application does something horribly bad, the best solution is to kill it as soon as possible to prevent serious damage to hardware, system or even your application data. When the system detects such dangerous situation, it sends a signal to the process (most often SIGSEGV, SIGFPE or SIGBUS) and aborts it right after. This may happen in any moment of execution of your program, for instance right after you tried to overwrite your own stack or even your own program code, effectively destroying data critical for the process to work. Thus you should consider any internal state of the program to be corrupt and unrecoverable.


I mean can we atleast popup a message showing the reason of the crash to the end user and write the same to a log file before quitting the application?

It should be safe to write something to a file. Doing anything with the GUI is not safe. If you are after playing some sound then you can play it using an external process (e.g. external player). This way, even if it crashes, your main program can continue safely.

sattu
28th January 2013, 15:10
the best solution is to kill it as soon as possible to prevent serious damage to hardware, system or even your application data.
Actually Wysota this problem is not exactly from application side because the wav files got corrupted. That's why I wanted to know how to handle such situations as they are not in our control.


If you are after playing some sound then you can play it using an external process (e.g. external player). This way, even if it crashes, your main program can continue safely.
Correct but then again not an option in our case :(. Sticking to QSound as of now :)

wysota
28th January 2013, 15:15
Actually Wysota this problem is not exactly from application side because the wav files got corrupted.
Of course it is the fault of the application. The library you are using for playing sounds apparently can't handle invalid files and causes a crash.


Correct but then again not an option in our case :(
Why not?

sattu
28th January 2013, 15:57
Of course it is the fault of the application. The library you are using for playing sounds apparently can't handle invalid files and causes a crash.
Well, we are using QSound. So, maybe I will see if I can work on the library part :confused:

pradeepreddyg95
28th January 2013, 17:39
with QProcess you can restart your appliaction when it crashed this is most useful in embedded linux .
Example:

#include "applicationcontrol.h"

ApplicationControl::ApplicationControl(QObject *parent) :
QObject(parent)
{


m_pProcess = new QProcess*[2];

for(int i = 0; i < 2; i++)
{
m_pProcess[i] = new QProcess();

m_pProcess[i]->setProcessChannelMode(QProcess::MergedChannels);
connect(m_pProcess[i], SIGNAL(finished(int, QProcess::ExitStatus)),this, SLOT(processFinished(int, QProcess::ExitStatus)));
connect(m_pProcess[i], SIGNAL(error(QProcess::ProcessError)),this, SLOT(processError(QProcess::ProcessError)));
}

m_pProcess[0]->setObjectName("Server");
m_pProcess[1]->setObjectName("Client");



QTimer::singleShot(5,this,SLOT(StartJob()));

m_nServerStarted = false;
m_nClientStarted = false;
}
void ApplicationControl::StartJob()
{
m_pProcess[0]->start("/root/CCU/Server");
m_pProcess[1]->start("/root/CCU/Client");

}

void ApplicationControl::processError(QProcess::Process Error error)
{

QProcess *pProcess = qobject_cast<QProcess*>(sender());

qDebug() << "Application Name " << pProcess->objectName();

if (error == QProcess::FailedToStart)
{
qDebug(("Unable to Start Job ..."));
return ;
}
else if (error == QProcess::Crashed)
{

qDebug() << "Program Crashed error " << error << QDateTime::currentDateTime().toString();
}
else if (error == QProcess::Timedout)
{
qDebug() << "Program Timedout error " << error << QDateTime::currentDateTime().toString();

}
else if (error == QProcess::WriteError)
{
qDebug() << "Program WriteError error " << error << QDateTime::currentDateTime().toString();

}
else if (error == QProcess::ReadError)
{
qDebug() << "Program ReadError error " << error << QDateTime::currentDateTime().toString();

}
else
{
qDebug() << "Program Unknow error " << error << QDateTime::currentDateTime().toString();

}

}
void ApplicationControl::processFinished(int exitCode, QProcess::ExitStatus exitStatus)
{
/* If crashed Restart Application */
QProcess *pProcess = qobject_cast<QProcess*>(sender());
qDebug() << "Application Name " << pProcess->objectName();
if(exitStatus == 0)
{
qDebug() << "exit Success Restarting " << pProcess->objectName();

return ;

}

if (exitStatus == QProcess::CrashExit)
{
qDebug() << "Program Crashed " << QDateTime::currentDateTime().toString();
// return ;

}
else if (exitCode != 0)
{
qDebug() << "Failed to Start" << QDateTime::currentDateTime().toString();
}

if(pProcess->objectName() == "Server")
{
m_pProcess[0]->start("/root/CCU/Server");
}
else if(pProcess->objectName() == "Client")
{
m_pProcess[1]->start("/root/CCU/Client");
}


}

sattu
29th January 2013, 08:54
Wow, thanks Pradeep. This code looks really great, I will try implementing it in my context.

Added after 17 minutes:


you can play it using an external process (e.g. external player). This way, even if it crashes, your main program can continue safely.

Hi Wysota, I tried playing wav files in a different process but I am encountering certain problem in it. Here's the way I implemented it:-




.h file
class customWavePlayer:public QSound
{
public:
customWavePlayer(const QString&, QObject*);
~customWavePlayer();
bool playWaveFile(QString filename, int vol);
};


.cpp file
customWavePlayer::customWavePlayer(const QString& str, QObject* parent):QSound(str,parent)
{
}

customWavePlayer::~customWavePlayer()
{
}

bool customWavePlayer::playWaveFile(QString filename, int vol)
{
static int child_pid=-1;
int status;
if(child_pid>0)
{
waitpid(child_pid, &status, 0);
}
child_pid=fork();
if(child_pid==0) //in child
{
qDebug("******************started playing");
play(filename,vol);
//while(!isFinished());
qDebug("******************finished playing");
//exit(EXIT_SUCCESS);
}
if(child_pid!=-1)
return true;
else
return false;
}


By this the file is playing but the application hangs. For more information our's is a multi-threaded GUI application. 4-5 different threads are running in the main application.
Can you suggest us some better way to play it in a different process?

wysota
29th January 2013, 11:51
You don't need to code your own player. I'm sure there are some available for your platform. Just install one and use it.

sattu
29th January 2013, 13:57
You don't need to code your own player. I'm sure there are some available for your platform. Just install one and use it.
Well, ok. Let me see to it.