I'm trying to run the following QT code :
#include <QtCore/QCoreApplication>
#include <QSharedMemory>
#include <QDebug>
QSharedMemory g_objSharedMemory(QString("Shared Memory"));
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
if(g_objSharedMemory.isAttached()==false)
{
qDebug()<<"Shared memory is not attached !!!!trying to attach it\n ";
qDebug()<<g_objSharedMemory.errorString();
if(g_objSharedMemory.attach()==false)
{
qDebug()<<"Failed to attach shared memory to the process!!!!";
qDebug()<<g_objSharedMemory.errorString();
return 0;
}
}
return a.exec();
}
I've failed to attach the shared memory segment to the process. I'm building this code on windows XP.
I'm getting QSharedMemory::handle doesnt exist error.
How can i fix this error?
You need to create() the shared memory segment in one of the processes which are using it. Most likely, you have one "master" or "server" process which is started first - let this process create the shared memory with a specific size:
qDebug()<<"Creating shared memory ...";
if(g_objSharedMemory.create(42) == false) {
qDebug() << "Failed to create shared memory!!!!";
qDebug() << g_objSharedMemory.errorString();
}
Then, in your "slave" or "client" processes, you should be able to attach to the shared memory with the same key.
Note that create() also attaches the process, so you must not call attach() in the master process.
Related
I have a function that reads a large file to fill a QStringList. The program crashes probably because there is not enough memory because if I use a small file the program runs well. I try to debug the problem by catching the exception.
QStringList readlargefile(QString filename)
{
QStringList result;
QFile file(filename);
if (!file.open(QIODevice::ReadOnly))
{
qDebug()<<"cannot open file: "<<filename;
return result;
}
QTextStream in(&file);
in.setCodec("UTF-8");
QString line;
while(in.readLineInto(&line))
{
if(!line.isEmpty())
result<<line;
}
file.close();
return result;
}
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
QStringList result;
try
{
qDebug()<<"reading file";
result=readlargefile("largefile.txt");
}
catch(...) {
qFatal("got exception");
}
}
The output is:
reading file
Killed
I cannot catch the exception, why?
If your program is aborted by OS it will not generate any exception. But you can setup a signal handler:
void signalHandler(int)
{
//...
}
int main(int argc, char* argv[])
{
signal(SIGINT , signalHandler);
signal(SIGTERM , signalHandler);
#ifdef Q_OS_WIN
signal(SIGBREAK, signalHandler);
#endif
The reason you can't catch std::bad_alloc is because Qt probably uses a no-throw version of ::new. Or new is OK but the Princess is in another castle.
There are two pitfalls you may stumble upon with your original problem (crash).
1. It can be a reallocating issue.
When the array is filled up already, and you try to insert more, it allocates a new array and copies (moves) data from the previous one. So you end up having two big arrays until copying (moving) is done. If you know the exact number of strings ahead, you can try preallocating the array to ensure there will be no reallocations. Use QList::reserve() for that.
2. Qt containers like QList and QVector can hold no more than 2GB of data.
If sizeof(QString) is 8 bytes, there will be allowed no more than 2^28 items.
It will crash eventually if you try to store more. Try std::vector (with reserve) and check if it works.
After all, if your system doesn't have enough memory for the task - it doesn't have enough memory, and there is nothing you can do about it but to change your algorithm.
I am a beginner in qt. It would be very helpful if this problem solved.
I would like to use QProcess to execute the file and show the real time output to the QTextviewer.
The file cannot stop running unless you press ctrl c in terminal command line. Otherwise, the file works well on terminal in linux.
The main problem occured was : the process did start by qt, however, I didn't see any output.
I try signal(readyReadStandardOutput) and slot. When I add waitforfinished(), the GUI will freezed.
if(!process)
{
process = new QProcess (this);
}
process -> setWorkingDirectory("mydir");
connect(process, SIGNAL(readyReadStandardOutput()), this, SLOT(logRead()));
connect(process, SIGNAL(readyReadStandardError()), this, SLOT(readError()));
process -> start("./file");
process -> setProcessChannelMode(QProcess::MergedChannels);
if(false == peocess-> waitForStarted())
{
ui -> textBrowser->append("the process cannot be called");
}else{
ui -> textBrowser->append("the process can be called");
}
textBrowser did show "the process can be called".
void Dialog::logRead()
{
QProcess *process = dynamic_cast<QProcess *>( sender() );
if (process){
ui->textBrowser->append( p->readAllStandardOutput() );
}
I dont know why I CANNOT output text in real time, even I didnt get any output!! Any suggestion? thank you!
Your problem, must be in a different part of your app. My minimal reproducible examples works like expected.
#include <QApplication>
#include <QDebug>
#include <QTextBrowser>
#include <QProcess>
int main(int argc, char* argv[])
{
QApplication a(argc, argv);
auto process = new QProcess;
auto view = new QTextBrowser;
process->setWorkingDirectory("C:/Temp");
QObject::connect(process, &QProcess::readyReadStandardOutput, [process,view]() {
auto output=process->readAllStandardOutput();
view->append(output);
});
QObject::connect(process, &QProcess::readyReadStandardError, [process,view]() {
auto output=process->readAllStandardError();
view->append(output);
});
process->start("MyProgram.exe");
process->setProcessChannelMode(QProcess::MergedChannels);
process->waitForStarted();
qDebug() << process->error();
view->show();
return a.exec();
}
I created a Qt app with a GUI that can also run on the command line (by never calling QMainWindow::show()). When I try to run it on a Debian virtual machine I get the error:
$ xvfb-run ./myApp
Could not initialize GLX
Aborted
I built it on Ubuntu 16.04 with dynamic linking to the Qt libs and copied over the needed libraries. It was previously working, but started giving this error after I updated the app. How can I find out if this error is due to missing dependency or some issue with xvfb?
$ xvfb-run ./myApp
Xvfb doesn't support GLX / OpenGL. That's all. Either use a full blown Xorg server with GPU drivers or a headless EGL context.
The problem is most likely because you instantiate QApplication or QGuiApplication: not showing the window is not enough. When you run from the command line, you also need to use QCoreApplication only.
#include <QtWidgets>
#include <memory>
#ifdef Q_OS_WIN
#include <io.h>
int isatty(int fd) { return _isatty(fd); }
#else
#include <unistd.h>
#endif
using MyWindow = QWidget;
bool onCommandLine() {
return isatty(0);
}
int main(int argc, char **argv) {
std::unique_ptr<QCoreApplication> app(
onCommandLine() ? new QCoreApplication(argc, argv)
: new QApplication(argc, argv));
/* common logic goes here, e.g. argument parsing, etc. */
if (!onCommandLine()) {
MyWindow w;
w.show();
return app->exec();
} else
return 0;
}
I looked up several examples how to create a single instance application and they all used create() and attach() methods of QSharedMemory. Why do they need attach()?
This seems to work perfectly:
bool SingleInstanceApplication::useSharedMemory()
{
_sharedMemory.setKey(_uniqueKey);
// If shared memory is created and attached successfuly,
// no other application instace is running
bool hasNoPreviousInstance = _sharedMemory.create(1);
return !hasNoPreviousInstance;
}
According to my understanding of the documentation. This has to be enough.
One example would be: http://developer.nokia.com/community/wiki/Run_only_one_instance_of_a_Qt_application
They need attach() because create() may fail for other reasons that the segment already exists. For example the system may be out of resources, or a shared memory segment creation is disabled for your application (by SELinux for example). In this case create() will return false but error() will return a different error code (such as QSharedMemory::OutOfResources) and you won't be able to find out that a segment already exists, while attach() would find it out.
I test a minimal case on a Linux distro:
#include <QCoreApplication>
#include <QSharedMemory>
#include <QDebug>
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
const char* MEM_KEY = "42";
QSharedMemory sharedMem(MEM_KEY);
if (sharedMem.create(1024)) {
qDebug() << "Create shared memory";
} else {
if (sharedMem.error() == QSharedMemory::AlreadyExists) {
qWarning() << "Already create. Exiting process";
return 1;
} else {
// handle other possible errors
}
}
return a.exec();
}
As you suggest, a call to create seems enough to make the attended error occur. In my understanding, attach is only called when a second process want to access an already created shared memory. But, that's not the purpose of a single application guard.
There is requirement of writing a Qt application on a MIPS based platform.
But there are lots of constraints. The constraints included freeing up of few resources (QGFX Plugin, GPU Memory etc) when required and re-using it. But the application cannot be killed as its handling lots of other requests and running other things.
Basically the GUI needs to be killed and free all the resources related to GUI; later when when required restart again
One of the way which has been tried is :
main() -> create a New-Thread
In the New-Thread,
while(<Condition>)
{
sem_wait(..)
m_wnd = new myMainWindow();
...
..
app->exec();
}
When ever there is a kill command, it comes out of the event loop, and wait for the signal from other threads. Once other threads does the required changes, it will get the signal and will create a new window and goes into the event loop.
In the main(), there are also few other threads created, which control other devices etc and signal the start and stop for the Qt-GUI.
The above seems to work but I am not sure if this is the right design. Does it create any problem?
Can any one suggest any better way?
I was able to find the required answer in Qt-Forums.
Since the main intention was to remove all the things related to GUI (On screen), I could use void setQuitOnLastWindowClosed ( bool quit ) (Details Here). This will make sure the GUI / Main window is closed and still the app doesnt come out of event loop and I can restart the main window later.
Thanks
When I needed a way to ensure that my app kept running, I forked it into a sub-process. That way, even if it seg-faulted, the main process would catch it and start a new child process. In the child process, I had multiple threads for GUI and non-GUI tasks. The fork code is short and is based on the example given in the wait(2) man page. The main() simply calls createChild() in a while loop. createChild() starts a new process using zmain(). zmain() is your QT app's main.
#include <QtGui/QApplication>
#include <QThread>
int zmain(int argc, char *argv[])
{
QApplication app(argc, argv, true);
app.setQuitOnLastWindowClosed(false);
QThread powerThread;
Power p;
p.moveToThread(&powerThread);
powerThread.start();
return app.exec();
}
// The following code is taken from the wait(2) man page and has been modified to run
// our Qt main() above in a child process. When the child terminates, it is automatically
// restarted.
#include <sys/wait.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
int createChild(int argc, char *argv[]) {
pid_t cpid, w;
int status;
cpid = fork();
if (cpid == -1) {
perror("fork");
exit(EXIT_FAILURE);
}
if (cpid == 0) { /* Code executed by child */
fprintf(stderr, "Child PID is %ld\n", (long) getpid());
exit(zmain(argc, argv));
} else { /* Code executed by parent */
do {
w = waitpid(cpid, &status, WUNTRACED | WCONTINUED);
if (w == -1) {
perror("waitpid");
return(EXIT_FAILURE);
}
if (WIFEXITED(status)) {
fprintf(stderr, "exited, status=%d\n", WEXITSTATUS(status));
} else if (WIFSIGNALED(status)) {
fprintf(stderr, "killed by signal %d\n", WTERMSIG(status));
} else if (WIFSTOPPED(status)) {
fprintf(stderr, "stopped by signal %d\n", WSTOPSIG(status));
} else if (WIFCONTINUED(status)) {
fprintf(stderr, "continued\n");
}
} while (!WIFEXITED(status) && !WIFSIGNALED(status));
if (WIFEXITED(status) && WEXITSTATUS(status) == 111)
return 111;
return EXIT_SUCCESS;
}
}
int
main(int argc, char *argv[])
{
while (111 != createChild(argc, argv)) {
}
}