( the report is <a href="https://bugs.kde.org/show_bug.cgi?id=302143">https://bugs.kde.org/show_bug.cgi?id=302143</a> )<br><br>The last couple of days (not sure why: I think triggered somehow by the virtuoso deadlocks Vishesh posted a patch for recently) <br>
I started hitting the nepomuk zombie processes bug, and so I figured this was a good opportunity to debug it.<br><br>Turns out the root cause is a (quite silly) QProcess bug. I found the source here: <br><a href="http://qt.gitorious.org/qt/qt/blobs/4.8/src/corelib/io/qprocess_unix.cpp">http://qt.gitorious.org/qt/qt/blobs/4.8/src/corelib/io/qprocess_unix.cpp</a><br>
The short version is: QProcess doesn't check errors properly.<br><br>The longer version:<br><br>When QProcess->start() is called, Qt creates a pipe to the process to get its exit value and output. <br>It does this with qt_create_pipe, which calls qt_safe_pipe. qt_safe_pipe, on failure, returns 1.<br>
If this happens, qt_create_pipe fails, sets errno, prints a warning:<br>[/usr/bin/nepomukservicestub] QProcessPrivate::createPipe: Cannot create pipe 0x1987228: Too many open files<br>and returns void, carefully ignoring the error. <br>
<br>The calling function, QProcessPrivate::startProcess, does not check errno, and thus continues on its merry <br>way assuming the pipe has been created successfully, and creates a QSocketNotifier with it. <br>Since the pipe is not valid, this fails and prints a warning:<br>
[/usr/bin/nepomukservicestub] QSocketNotifier: Invalid socket specified<br><br>The calling process again does not check for an error, continues on its merry way and <br>forks off the child process (incidentally obliterating the value of errno from qt_create_pipe). <br>
Note that since the child process is actually created correctly, no QProcess error is set, <br>so we can't fix it by checking for error().<br><br>The child process then has no way to pass its exit value to the calling process, since the <br>
communication pipes it would normally use do not exist, and thus when it exits it becomes<br>a zombie. <br><br>As a bonus, once the first timeout timer for a broken process happens, waitForFinished is called, <br>which crashes, because it is trying to wait on a pipe which does not exist.<br>
(This was reported with a patch a year ago, but not fixed:<br><a href="https://bugreports.qt-project.org/browse/QTBUG-18934">https://bugreports.qt-project.org/browse/QTBUG-18934</a> )<br><br>There is another KDE bug which seems to have the same root cause:<br>
<a href="https://bugs.kde.org/show_bug.cgi?id=252602">https://bugs.kde.org/show_bug.cgi?id=252602</a><br><br>So far as I can see, this really needs to be fixed in QProcess. <br>The fix would, I guess, make qt_create_pipe return an integer, and <br>
then have startProcess check the return value, <br>set processError and abort.<br><br>Can this be done in a reasonable timeframe? Does anyone know how to submit Qt patches?<br><br>Simeon<br>