Results 1 to 12 of 12

Thread: My program crashes if QProcess is restarted directly when it has finished

  1. #1
    Join Date
    Nov 2011
    Posts
    51
    Thanks
    11
    Thanked 1 Time in 1 Post
    Qt products
    Qt4
    Platforms
    Windows

    Default My program crashes if QProcess is restarted directly when it has finished

    I have created a program that is supposed to run a process over and over again, so that the program is restarted as soon as it it finished. Here is the code that handles that:

    Qt Code:
    1. // From process_handler.h
    2. class process_handler : public QObject
    3. {
    4. Q_OBJECT
    5.  
    6. public:
    7. process_handler();
    8.  
    9. private:
    10.  
    11. public slots:
    12. void start_process();
    13.  
    14. private slots:
    15. void process_state_changed();
    16. };
    To copy to clipboard, switch view to plain text mode 

    Qt Code:
    1. // From process_handler.cpp
    2. process_handler::process_handler()
    3. {
    4. connect(&p, SIGNAL(stateChanged(QProcess::ProcessState)), this, SLOT(process_state_changed()));
    5. }
    6.  
    7. void process_handler::process_state_changed()
    8. {
    9. if (p.state() == QProcess::Starting) {
    10. cout << endl;
    11. cout << "Process is starting up..." << endl;
    12. }
    13. if (p.state() == QProcess::Running) {
    14. cout << "Process is now running." << endl;
    15. }
    16. if (p.state() == QProcess::NotRunning) {
    17. cout << "Process is finished running." << endl;
    18.  
    19. /* Start a new process */
    20. //start_process();
    21. QTimer::singleShot(0, this, SLOT(start_process()));
    22. }
    23. }
    24.  
    25. void process_handler::start_process()
    26. {
    27. p.start("program");
    28. }
    To copy to clipboard, switch view to plain text mode 

    "program" is a program that takes a few seconds to run and thex terminates. As you see I have used a QTimer::singleShot to call start_process() from process_state_changed(). If I don't use it, but call start_process() directly, the text

    Qt Code:
    1. Process is starting up...
    2. Process is now running.
    3. Process is finished running.
    4.  
    5. Process is starting up...
    6. Process is now running.
    To copy to clipboard, switch view to plain text mode 

    is written to cout and then I get a segmentation fault. Does anyone know why this segmentation fault occurs? I would like it if I didn't have to use a singleShot, since that will make coding much more complicated later on.

  2. #2
    Join Date
    Jan 2008
    Location
    Alameda, CA, USA
    Posts
    5,230
    Thanks
    302
    Thanked 864 Times in 851 Posts
    Qt products
    Qt5
    Platforms
    Windows

    Default Re: My program crashes if QProcess is restarted directly when it has finished

    Not a whole lot of error or status checking in that code. Do you even know that "program" runs when you start it the first time? How do you start it the first time?

    Also don't know why you aren't using the QProcess:ProcessState argument of the stateChanged signal in your slot instead of repeatedly calling p.state().

    You're not assigning a parent QObject to your QProcess member variable, nor are you assigning one to your process_handler instance, even though both inherit from QObject.

    I doubt that any of this is the cause of your problem. My guess is that there is some side effect of running "program" the first time that results in the crash the second time around. Try substituting something trivial for your own "program" and see if that changes things.

  3. #3
    Join Date
    Mar 2009
    Location
    Brisbane, Australia
    Posts
    7,729
    Thanks
    13
    Thanked 1,610 Times in 1,537 Posts
    Qt products
    Qt4 Qt5
    Platforms
    Unix/X11 Windows
    Wiki edits
    17

    Default Re: My program crashes if QProcess is restarted directly when it has finished

    Try running your program in your debugger and, when it crashes, using the stack backtrace to locate where it crashes from. There's nothing in the code you posted that is an obvious source, and it runs fine here with "sleep 5" as the command.

  4. #4
    Join Date
    Nov 2011
    Posts
    51
    Thanks
    11
    Thanked 1 Time in 1 Post
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: My program crashes if QProcess is restarted directly when it has finished

    Thank you for your answers.

    Quote Originally Posted by d_stranz View Post
    Not a whole lot of error or status checking in that code. Do you even know that "program" runs when you start it the first time? How do you start it the first time?
    What do you mean with error or status checking? I have done some debugging to try to see where the bug is and I'm checking the status of the process in process_state_changed(), but I'm not sure that is what you mean. I know the program is running because it lets me wait at least 10 seconds before it terminates. What do you mean by how I start it? I start it by calling p[idx].start("program");, where "program.exe" is a program I have put in the project folder.

    Quote Originally Posted by d_stranz View Post
    Also don't know why you aren't using the QProcess:ProcessState argument of the stateChanged signal in your slot instead of repeatedly calling p.state().
    Originally I had a lot of QProcesses stored in a vector, and all of them had to be connected to the process_handler::process_state_changed slot. But since the normal connection function will not let the slot know which object it is that has emitted the signal, I had to use a QSignalMapper to map the different processes to their indexes and connect their stateChanged signals with the map() slot of the QSignalMapper and connect the mapped(int) signal of the QSignalMapper to my process_handler::process_state_changed slot. So now I didn't have the QProcess::ProcessState anymore and I had to find out which state the process had changed to by calling p.state(), where idx was the index of the process.

    This example is just a simplification of it to generate the same behaviour with less code.

    Quote Originally Posted by d_stranz View Post
    You're not assigning a parent QObject to your QProcess member variable, nor are you assigning one to your process_handler instance, even though both inherit from QObject.
    Why should I? My QProcess object will be destroyed anyway when the process_handler is destroyed, and the the process_handler object is a direct member of the main window so it will automatically be destroyed when the main window is destroyed. But maybe I should update the process_handler constructor with a parameter that takes a pointer to the parent.

    Quote Originally Posted by d_stranz View Post
    I doubt that any of this is the cause of your problem. My guess is that there is some side effect of running "program" the first time that results in the crash the second time around. Try substituting something trivial for your own "program" and see if that changes things.
    I tried replacing it with "ls", but I still have the same problem; it crashes after the second time the process state has just changed to QProcess::Running. If I use the QSingleShot approach, the program calls the process over and over again without crashing.

    Quote Originally Posted by ChrisW67 View Post
    Try running your program in your debugger and, when it crashes, using the stack backtrace to locate where it crashes from. There's nothing in the code you posted that is an obvious source, and it runs fine here with "sleep 5" as the command.
    The segmentation fault occurs in qtimer.cpp, which just contains a bunch of assembly code. Then I have to backtrace through eleven more Qt files, before ending up in a Windows dll (user32.dll). Then it backtraces through two more Qt files and two more Window dlls. At place 18 it just says "??" in the function field, which I have no idea why it does. May the program stack has been corrupted?

  5. #5
    Join Date
    Feb 2008
    Posts
    491
    Thanks
    12
    Thanked 142 Times in 135 Posts
    Qt products
    Qt4 Qt5
    Platforms
    Unix/X11

    Default Re: My program crashes if QProcess is restarted directly when it has finished

    Quote Originally Posted by Yes View Post
    I would like it if I didn't have to use a singleShot, since that will make coding much more complicated later on.
    Why not connect the signal QProcess::finished(int) to your slot?
    Last edited by norobro; 14th September 2012 at 00:23. Reason: added quote

  6. #6
    Join Date
    Mar 2009
    Location
    Brisbane, Australia
    Posts
    7,729
    Thanks
    13
    Thanked 1,610 Times in 1,537 Posts
    Qt products
    Qt4 Qt5
    Platforms
    Unix/X11 Windows
    Wiki edits
    17

    Default Re: My program crashes if QProcess is restarted directly when it has finished

    You are saying the actual code posted above, with a minimal main() fails. You don't say what line 18 lists as the source file and line. Is it your code? Has your program been built in debug mode?

    The vast majority of segmentation faults are caused by programmers using dangling or uninitialised pointers (or undefined references). There are no pointers in your example code, except for a pointer to p that can only become invalid during program tear-down. It seems likely that the actual code you are running is more complex and is suffering a dangling pointer issue.

  7. #7
    Join Date
    Jan 2008
    Location
    Alameda, CA, USA
    Posts
    5,230
    Thanks
    302
    Thanked 864 Times in 851 Posts
    Qt products
    Qt5
    Platforms
    Windows

    Default Re: My program crashes if QProcess is restarted directly when it has finished

    I agree with ChrisW67 - since your actual code is undoubtedly more complex than what you have posted, the error probably lies elsewhere in the code and the crash in QTimer is simply a red herring brought about by the fact that the stack or heap have been corrupted earlier on.

    But since the normal connection function will not let the slot know which object it is that has emitted the signal
    Not true. See QObject::sender().

  8. #8
    Join Date
    Nov 2011
    Posts
    51
    Thanks
    11
    Thanked 1 Time in 1 Post
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: My program crashes if QProcess is restarted directly when it has finished

    Quote Originally Posted by norobro View Post
    Why not connect the signal QProcess::finished(int) to your slot?
    That is one way to do it too, but now I wanted to use the stateChanged signal. It's possible that I'll change to using the finished signal later on if I notice that I don't need to know when it changes to states other than QProcess::NotRunning.

    Quote Originally Posted by ChrisW67 View Post
    You are saying the actual code posted above, with a minimal main() fails. You don't say what line 18 lists as the source file and line. Is it your code? Has your program been built in debug mode?
    What do you mean with line 18? There isn't any line 18 in the code I posted with code on it... Yes, this is my code and I have tried running it in debug mode (see my last post).

    Quote Originally Posted by ChrisW67 View Post
    The vast majority of segmentation faults are caused by programmers using dangling or uninitialised pointers (or undefined references). There are no pointers in your example code, except for a pointer to p that can only become invalid during program tear-down. It seems likely that the actual code you are running is more complex and is suffering a dangling pointer issue.
    I don't think I have any dangling pointer anywhere since I never use the keyword new (or malloc or anything like that), but maybe some pointer is created somewhere that I am not aware of. I had better post the entire code here:

    main.cpp:
    Qt Code:
    1. #include <QtGui/QApplication>
    2. #include "mainwindow.h"
    3.  
    4. int main(int argc, char *argv[])
    5. {
    6. QApplication a(argc, argv);
    7. MainWindow w;
    8. w.show();
    9.  
    10. return a.exec();
    11. }
    To copy to clipboard, switch view to plain text mode 

    mainwindow.h:
    Qt Code:
    1. #ifndef MAINWINDOW_H
    2. #define MAINWINDOW_H
    3.  
    4. #include <QMainWindow>
    5. #include "process_handler.h"
    6.  
    7. namespace Ui {
    8. class MainWindow;
    9. }
    10.  
    11. class MainWindow : public QMainWindow
    12. {
    13. Q_OBJECT
    14.  
    15. public:
    16. explicit MainWindow(QWidget *parent = 0);
    17. ~MainWindow();
    18.  
    19. private:
    20. Ui::MainWindow *ui;
    21. process_handler s;
    22. };
    23.  
    24. #endif // MAINWINDOW_H
    To copy to clipboard, switch view to plain text mode 

    mainwindow.cpp:
    Qt Code:
    1. #include <QTimer>
    2. #include "mainwindow.h"
    3. #include "ui_mainwindow.h"
    4.  
    5. MainWindow::MainWindow(QWidget *parent) :
    6. QMainWindow(parent),
    7. ui(new Ui::MainWindow)
    8. {
    9. ui->setupUi(this);
    10.  
    11. /* Begin start processes when the windows has finished loading */
    12. QTimer::singleShot(0, &s, SLOT(start_process()));
    13. }
    14.  
    15. MainWindow::~MainWindow()
    16. {
    17. delete ui;
    18. }
    To copy to clipboard, switch view to plain text mode 

    process_handler.h:
    Qt Code:
    1. #ifndef PROCESS_HANDLER_H
    2. #define PROCESS_HANDLER_H
    3.  
    4. #include <QProcess>
    5.  
    6. class process_handler : public QObject
    7. {
    8. Q_OBJECT
    9.  
    10. public:
    11. process_handler(QObject *parent = 0);
    12.  
    13. private:
    14.  
    15. public slots:
    16. void start_process();
    17.  
    18. private slots:
    19. void process_state_changed();
    20. };
    21.  
    22. #endif // PROCESS_HANDLER_H
    To copy to clipboard, switch view to plain text mode 

    process_handler.cpp:
    Qt Code:
    1. #include <iostream>
    2. using std::cout;
    3. using std::endl;
    4. #include <QTimer>
    5. #include "process_handler.h"
    6.  
    7. process_handler::process_handler(QObject *parent) :
    8. QObject(parent)
    9. {
    10. connect(&p, SIGNAL(stateChanged(QProcess::ProcessState)), this, SLOT(process_state_changed()));
    11. }
    12.  
    13. void process_handler::process_state_changed()
    14. {
    15. if (p.state() == QProcess::Starting) {
    16. cout << endl;
    17. cout << "Process is starting up..." << endl;
    18. }
    19. if (p.state() == QProcess::Running) {
    20. cout << "Process is now running." << endl;
    21. }
    22. if (p.state() == QProcess::NotRunning) {
    23. cout << "Process is finished running." << endl;
    24.  
    25. /* Start a new process */
    26. start_process();
    27. //QTimer::singleShot(0, this, SLOT(start_process()));
    28. }
    29. }
    30.  
    31. void process_handler::start_process()
    32. {
    33. //p.start("program");
    34. p.start("ls");
    35. }
    To copy to clipboard, switch view to plain text mode 

    As can be seen, main.cpp is unmodified, and only one line each has been added to mainwindow.cpp and two lines to mainwindow.h, dealing with the process_handler object. As I said before, it is possible to make a workaround by using a QTimer::SingleShot (substitude line 27 in process_handler.cpp for line 26), but this is a hack I would definitely prefer not having to use.

    Quote Originally Posted by d_stranz View Post
    Not true. See QObject::sender().
    Thanks! I didn't know about that function, it seems handy.
    Last edited by Yes; 17th September 2012 at 16:13.

  9. #9
    Join Date
    Feb 2008
    Posts
    491
    Thanks
    12
    Thanked 142 Times in 135 Posts
    Qt products
    Qt4 Qt5
    Platforms
    Unix/X11

    Default Re: My program crashes if QProcess is restarted directly when it has finished

    Quote Originally Posted by Yes View Post
    . . . but now I wanted to use the stateChanged signal. . . .
    Then connecting both signals should work:
    Qt Code:
    1. process_handler::process_handler(QObject *parent) :
    2. QObject(parent)
    3. {
    4. connect(&p, SIGNAL(stateChanged(QProcess::ProcessState)), this, SLOT(process_state_changed(QProcess::ProcessState)));
    5. connect(&p, SIGNAL(finished()), this, SLOT(start_process()));
    6. }
    7.  
    8. void process_handler::process_state_changed(QProcess::ProcessState state)
    9. {
    10. if (state == QProcess::Starting) {
    11. cout << endl;
    12. cout << "Process is starting up..." << endl;
    13. }
    14. if (state == QProcess::Running) {
    15. cout << "Process is now running." << endl;
    16. }
    17. if (state == QProcess::NotRunning) {
    18. cout << "Process is finished running." << endl;
    19.  
    20. /* Start a new process */
    21. // start_process();
    22. //QTimer::singleShot(0, this, SLOT(start_process()));
    23. }
    24. }
    25.  
    26. . . .
    To copy to clipboard, switch view to plain text mode 

  10. #10
    Join Date
    Nov 2011
    Posts
    51
    Thanks
    11
    Thanked 1 Time in 1 Post
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: My program crashes if QProcess is restarted directly when it has finished

    Quote Originally Posted by norobro View Post
    Then connecting both signals should work
    Yes, but I don't want to start a new process every time an old process has finished. Basically, I want to run processes untill some condition is reached, and then I want to stop running processes, so start_process() shouldn't be directly connected to the finished signal since then I wouldn't be able to stop running processes. The question is still why my program crashes if I call start_process() directly from process_state_changed() without using a QTimer::SingleShot...

  11. #11
    Join Date
    Feb 2008
    Posts
    491
    Thanks
    12
    Thanked 142 Times in 135 Posts
    Qt products
    Qt4 Qt5
    Platforms
    Unix/X11

    Default Re: My program crashes if QProcess is restarted directly when it has finished

    Apparently notRunning != finished(). On Linux I get the following warning on the command line:
    QSocketNotifier: Multiple socket notifiers for same socket 15 and type Read
    Try the following code:
    Qt Code:
    1. #include <QCoreApplication>
    2. #include <QProcess>
    3. #include <QDebug>
    4. #include <QTimer>
    5.  
    6. class process_handler : public QObject
    7. {
    8. Q_OBJECT
    9. public:
    10. process_handler() {
    11. connect(&p, SIGNAL(stateChanged(QProcess::ProcessState)), this, SLOT(process_state_changed(QProcess::ProcessState)));
    12. connect(&p, SIGNAL(finished(int, QProcess::ExitStatus)), this, SLOT(process_finished(int, QProcess::ExitStatus)));
    13. start_process();
    14. }
    15. public slots:
    16. void process_state_changed(QProcess::ProcessState state) {
    17. if (state == QProcess::Starting)
    18. qDebug() << "Process is starting up...";
    19. if (state == QProcess::Running)
    20. qDebug() << "Process is now running." ;
    21. if (state == QProcess::NotRunning){
    22. qDebug() << "Process is finished running.";
    23. start_process();
    24. //QTimer::singleShot(0, this, SLOT(start_process()));
    25. }
    26. }
    27. void process_finished(int , QProcess::ExitStatus ){
    28. qDebug() << "received finished signal";
    29. }
    30. void start_process() {
    31. p.start("ping 1.1.1.1 -c 1 -W 3"); // from your previous thread
    32. }
    33. private:
    34. };
    35.  
    36. int main(int argc, char *argv[]) {
    37. QCoreApplication app(argc, argv);
    38. process_handler ph;
    39. app.exec();
    40. }
    41. #include "main.moc"
    To copy to clipboard, switch view to plain text mode 
    The output on my box is:
    Process is starting up...
    Process is now running.
    Process is finished running.
    QSocketNotifier: Multiple socket notifiers for same socket 15 and type Read
    Process is starting up...
    received finished signal
    I haven't looked at the source code but what appears to happen is the new process assigns a QSocketNotifier to the same
    socket as the old process and the old process deletes the socket. My app just idles in the event loop after the output
    above. Maybe Windows segfaults?

  12. The following user says thank you to norobro for this useful post:

    Yes (18th September 2012)

  13. #12
    Join Date
    Nov 2011
    Posts
    51
    Thanks
    11
    Thanked 1 Time in 1 Post
    Qt products
    Qt4
    Platforms
    Windows

    Thumbs up Re: My program crashes if QProcess is restarted directly when it has finished

    Okay, so maybe I need to wait untill I receive the finished signal before I can start up a new process.

    Yes, I'm using Windows XP and I do receive a segmentation fault message. The output of your code in the command prompt (the terminal in Windows) before the segfault message comes is

    Process is starting up...
    Process is now running.
    Process is finished running.
    Process is starting up...
    Process is now running.
    received finished signal
    I don't get the same QSocketNotifier message as you do, though. I still only get to see Qt files containing a lot of assembly code when backtracing.

    However, if I move the line containing start_process(); from the slot receiving the stateChanged signal to the slot receiving the finished signal, the program runs as expected. I think I will just stick to the QTimer::singleShot() workaround in my case, though. Anyway, thank you very much!

Similar Threads

  1. Replies: 2
    Last Post: 13th July 2011, 03:52
  2. Replies: 0
    Last Post: 26th August 2010, 11:44
  3. QProcess::finished problems again
    By mdicosimo in forum Qt Programming
    Replies: 2
    Last Post: 23rd January 2009, 22:43
  4. QProcess::finished()
    By T1c4L in forum Qt Programming
    Replies: 11
    Last Post: 9th July 2008, 21:06
  5. Replies: 4
    Last Post: 13th February 2006, 12:35

Tags for this Thread

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
Digia, Qt and their respective logos are trademarks of Digia Plc in Finland and/or other countries worldwide.