Russian Qt Forum

Qt => Общие вопросы => Тема начата: XpycT от Январь 26, 2010, 04:53



Название: QThread + QProcess и краш программы
Отправлено: XpycT от Январь 26, 2010, 04:53
Пытаюсь запустить в новом потоке батник, который в свою очередь запускает java. Проблема состоит в том, что при втором завершении дерева процессов программа вылетает в отладчик. Подскажите что не так.

serverthread.h
Код
C++ (Qt)
#ifndef SERVERTHREAD_H
#define SERVERTHREAD_H
 
#include <QThread>
 
class QProcess;
 
class ServerThread : public QThread
{
   Q_OBJECT
 
public:
    void run();
 
public slots:
    void kill();
    void output();
 
signals:
    void updateOutput(QString msg);
 
private:
   QProcess *process;
};
 
#endif // SERVERTHREAD_H
 
serverthread.cpp
Код
C++ (Qt)
#include "serverthread.h"
#include "Windows.h"
#include <QProcess>
#include <QTextCodec>
#include <QDebug>
void ServerThread::run()
{
   process = new QProcess(this);
   process->setProcessChannelMode(QProcess::MergedChannels);
   connect(process, SIGNAL(readyReadStandardOutput()), this, SLOT(output()));
   process->setWorkingDirectory("E:\\server");
   process->start("E:\\server\\server.bat");
   exec();
}
void ServerThread::output(){
   QByteArray bytes = process->readAllStandardOutput();
   QTextCodec *codec = QTextCodec::codecForName("IBM 866");
   QString string = codec->toUnicode(bytes);
   emit updateOutput(string);
}
 
 
void ServerThread::kill(){
   /*
    * HACK: QProcess::kill() just kills the process. Under Windows, this is
    * suboptimal because if the process was a batch file which spawned
    * other processes, those processes will be orphaned. The best way is
    * to kill the whole process tree manually. Under XP, there is an
    * internal command called TASKKILL which handles this. To do this
    * portably, we will have to iterate through the process list manually.
    */

 #ifdef Q_WS_WIN
   QString abort_cmd;
   PROCESS_INFORMATION *pinfo = (PROCESS_INFORMATION  *)process->pid();
   abort_cmd = QString("taskkill /F /T /PID %1").arg(pinfo->dwProcessId);
   QProcess pr;
   pr.execute(abort_cmd);
   qDebug()<<abort_cmd << pr.state();
 #endif
}
 

и вызов по кнопке старта и кила
Код
C++ (Qt)
ServerThread th;
   connect(&th,SIGNAL(updateOutput(QString)),this,SLOT(setOutput(QString))); // вывод текста с потока
   connect(pushButton_2,SIGNAL(clicked()),&th,SLOT(kill())); // сигнал кила, первый раз проходит а второй вызывает краш
   th.run();


Название: Re: QThread + QProcess и краш программы
Отправлено: ilyagoo от Январь 26, 2010, 10:02
первое, что приходит в голову:
Код:
th.run();
запускать поток нужно так
Код:
th.start();

второе - соединяй сигналы со слотами между потоками с флагом Qt::QueuedConnection


Название: Re: QThread + QProcess и краш программы
Отправлено: Akaiten от Январь 26, 2010, 10:45
первое, что приходит в голову:
Код:
th.run();
запускать поток нужно так
Код:
th.start();
Правильно подмечено, а то у тебя от потока только одно название, код выполняется в главном потоке.

Обрати внимание, что QProcess::execute - статический метод и вместо
Код
C++ (Qt)
QProcess pr;
pr.execute(abort_cmd);
 
в следующий раз пиши просто
Код
C++ (Qt)
QProcess::execute(abort_cmd);

А проблема краша мне кажется в то, что  process->pid() возвращает 0, если процесс в текущий момент не выполняется, поэтому и указатель pinfo невалидный.


Название: Re: QThread + QProcess и краш программы
Отправлено: XpycT от Январь 26, 2010, 13:31
А проблема краша мне кажется в то, что  process->pid() возвращает 0, если процесс в текущий момент не выполняется, поэтому и указатель pinfo невалидный.

Спасибо за направление, все выше сказанное не помогло, а вот с pid'ом и была проблема, вернее сам process->pid() работает корректно и возвращает инфу всегда, но вот проблемный код был в
Код
C++ (Qt)
PROCESS_INFORMATION *pinfo = (PROCESS_INFORMATION  *)process->pid();
Попросту вынес его из слота kill() в слот run() и краши пропали.



Название: Re: QThread + QProcess и краш программы
Отправлено: Akaiten от Январь 26, 2010, 17:07
QProcess::pid() под Windows возвращает указатель на структуру PROCESS_INFORMATION, при чём память под неё выделяется динамически... При завершении процесса память освобождается и указатель обнуляется.


Название: Re: QThread + QProcess и краш программы
Отправлено: XpycT от Январь 27, 2010, 12:25
Вылезла еще одна проблема:
Скинул человеку, чтобы он проверил на Windows 7, и он говорит что при старте сервера программа крашится..получается идет создание ServerThread, в котором как раз вызывается
Код
C++ (Qt)
#include "Windows.h"
и
Код
C++ (Qt)
PROCESS_INFORMATION *pinfo = (PROCESS_INFORMATION  *)process->pid();

Так вот как я понял тут может быть 3 причины:
1) Идет обращение к старому winAPI, которого как я понимаю в windows 7 может не быть
2) не верно на семерке обрабатывается директива #ifdef Q_WS_WIN...#endif
3) Что-то не так с созданием QProcess

Может кто сталкивался?


Название: Re: QThread + QProcess и краш программы
Отправлено: Akaiten от Январь 27, 2010, 15:07
Уверен, что в этом дело? Может ему надо установить VS 2008 (или какая у тебя там студия) Redistributable Package?


Название: Re: QThread + QProcess и краш программы
Отправлено: XpycT от Январь 27, 2010, 17:23
я open source сборку использую. и там с прогой mingw10.dll и libgcc_s_dw2-1.dll вкидывал