Russian Qt Forum
Ноябрь 26, 2024, 22:45 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: [1]   Вниз
  Печать  
Автор Тема: QThread + QProcess и краш программы  (Прочитано 5176 раз)
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();
Записан
ilyagoo
Гость
« Ответ #1 : Январь 26, 2010, 10:02 »

первое, что приходит в голову:
Код:
th.run();
запускать поток нужно так
Код:
th.start();

второе - соединяй сигналы со слотами между потоками с флагом Qt::QueuedConnection
Записан
Akaiten
Гость
« Ответ #2 : Январь 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 невалидный.
Записан
XpycT
Гость
« Ответ #3 : Январь 26, 2010, 13:31 »

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

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

Записан
Akaiten
Гость
« Ответ #4 : Январь 26, 2010, 17:07 »

QProcess::pid() под Windows возвращает указатель на структуру PROCESS_INFORMATION, при чём память под неё выделяется динамически... При завершении процесса память освобождается и указатель обнуляется.
Записан
XpycT
Гость
« Ответ #5 : Январь 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

Может кто сталкивался?
Записан
Akaiten
Гость
« Ответ #6 : Январь 27, 2010, 15:07 »

Уверен, что в этом дело? Может ему надо установить VS 2008 (или какая у тебя там студия) Redistributable Package?
Записан
XpycT
Гость
« Ответ #7 : Январь 27, 2010, 17:23 »

я open source сборку использую. и там с прогой mingw10.dll и libgcc_s_dw2-1.dll вкидывал
Записан
Страниц: [1]   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.555 секунд. Запросов: 21.