Search code examples
qtprocessforkwaitqthread

Forked (background) Qt app will not exit properly


I have a multithreaded Qt/C++ app that works great in the foreground, but when it dameonizes it will not shutdown properly. The process remains active but hung in a waiting see - see backtrace of waiting program:

(gdb) bt
#0  0x000000372460b575 in pthread_cond_wait@@GLIBC_2.3.2 () from /lib64/libpthread.so.0
#1  0x00007f8990fb454b in QWaitCondition::wait(QMutex*, unsigned long) ()
   from /opt/Qt/5.1.1/gcc_64/lib/libQt5Core.so.5
#2  0x00007f8990fb3b3e in QThread::wait(unsigned long) () from /opt/Qt/5.1.1/gcc_64/lib/libQt5Core.so.5
#3  0x00007f8990fb0402 in QThreadPoolPrivate::reset() () from /opt/Qt/5.1.1/gcc_64/lib/libQt5Core.so.5
#4  0x00007f8990fb0561 in QThreadPool::waitForDone(int) () from /opt/Qt/5.1.1/gcc_64/lib/libQt5Core.so.5
#5  0x00007f89911a4261 in QMetaObject::activate(QObject*, int, int, void**) ()
   from /opt/Qt/5.1.1/gcc_64/lib/libQt5Core.so.5
#6  0x00007f89911a4d5f in QObject::destroyed(QObject*) () from /opt/Qt/5.1.1/gcc_64/lib/libQt5Core.so.5
#7  0x00007f89911aa3ee in QObject::~QObject() () from /opt/Qt/5.1.1/gcc_64/lib/libQt5Core.so.5
#8  0x0000000000409d8b in main (argc=1, argv=0x7fffba44c8f8) at ../../src/main.cpp:27
(gdb) 

I realize now that my code first creates a thread, and then forks, in case that matter. The foreground process exits normally (confirmed that PID is gone), but the background pid never ends. Could this have something to do with the fact that I created my QThread in the parent? If so, how do I make this waiting thread die?

If not, is there a special way to exit a console app that's been daemonized? (in Qt)


Solution

  • Qt is not tested to interoperate with fork(), so don't expected it to be supported. It's non-portable and, in most cases, unnecessary.

    You should spawn yourself using a detached QProcess, then promptly exit. If you need to do any initialization in the spawned process, you can pass the relevant data to the child.

    My other answer illustrates the basics of this technique, and is portable to all platforms that Qt runs on. You'd be using QProcess::startDetached in this case to start the child process in its own session to act like a daemon.

    You might also want to have a look at the QtService solution. It is portable between Unix and Windows, on the former it uses daemonization, on the latter it uses the native service API.