1

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)

TSG
  • 4,242
  • 9
  • 61
  • 121

1 Answers1

1

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.

Community
  • 1
  • 1
Kuba hasn't forgotten Monica
  • 95,931
  • 16
  • 151
  • 313
  • I wasn't aware of this! Can you point to a link about not using fork, and one about how to achieve the same wiht QProcess? (I'll check the Nokia docs too) Thanks – TSG Feb 25 '14 at 21:11
  • 1
    Here is a related question: http://stackoverflow.com/questions/21514446/get-pid-of-process-after-fork-in-qt – phyatt Feb 25 '14 at 21:20
  • @Michelle The "link" is simply a grep of Qt sources. `fork` does not figure anywhere in the test cases (outside of the perl test executor code). It's not tested for, so expecting it to reliably work is pretty much out of question. – Kuba hasn't forgotten Monica Feb 25 '14 at 21:24
  • @Michelle You cannot achieve "the same" with `QProcess`, since the whatever `QProcess` starts does not share the memory nor other resources with your process. The only thing you can do is pass data on the command line, using `QSharedMemory`, or using a pipe (a.k.a `QLocalSocket`). You need to architect things as if you were on Windows, pretty much - forget about `fork`. – Kuba hasn't forgotten Monica Feb 25 '14 at 21:26
  • You're right - I reworked my code so my main immediately forks, and then lets Qt does it thing (initialize, setup signals, etc), and now it's happy. Qt just didn't like forking... – TSG Feb 26 '14 at 01:05