[prev in list] [next in list] [prev in thread] [next in thread] 

List:       nepomuk
Subject:    [Nepomuk] The zombie processes bug ( 302143 )
From:       Simeon Bird <bladud () gmail ! com>
Date:       2012-12-12 2:28:43
Message-ID: CAKRKD_UOJiMexr9nbrfx_jRupkHSmACVMdhUJo46ES7puM5diw () mail ! gmail ! com
[Download RAW message or body]

[Attachment #2 (multipart/alternative)]


( the report is https://bugs.kde.org/show_bug.cgi?id=302143 )

The last couple of days (not sure why: I think triggered somehow by the
virtuoso deadlocks Vishesh posted a patch for recently)
I started hitting the nepomuk zombie processes bug, and so I figured this
was a good opportunity to debug it.

Turns out the root cause is a (quite silly) QProcess bug. I found the
source here:
http://qt.gitorious.org/qt/qt/blobs/4.8/src/corelib/io/qprocess_unix.cpp
The short version is: QProcess doesn't check errors properly.

The longer version:

When QProcess->start() is called, Qt creates a pipe to the process to get
its exit value and output.
It does this with qt_create_pipe, which calls qt_safe_pipe. qt_safe_pipe,
on failure, returns 1.
If this happens, qt_create_pipe fails, sets errno, prints a warning:
[/usr/bin/nepomukservicestub] QProcessPrivate::createPipe: Cannot create
pipe 0x1987228: Too many open files
and returns void, carefully ignoring the error.

The calling function, QProcessPrivate::startProcess, does not check errno,
and thus continues on its merry
way assuming the pipe has been created successfully, and creates a
QSocketNotifier with it.
Since the pipe is not valid, this fails and prints a warning:
[/usr/bin/nepomukservicestub] QSocketNotifier: Invalid socket specified

The calling process again does not check for an error, continues on its
merry way and
forks off the child process (incidentally obliterating the value of errno
from qt_create_pipe).
Note that since the child process is actually created correctly, no
QProcess error is set,
so we can't fix it by checking for error().

The child process then has no way to pass its exit value to the calling
process, since the
communication pipes it would normally use do not exist, and thus when it
exits it becomes
a zombie.

As a bonus, once the first timeout timer for a broken process happens,
waitForFinished is called,
which crashes, because it is trying to wait on a pipe which does not exist.
(This was reported with a patch a year ago, but not fixed:
https://bugreports.qt-project.org/browse/QTBUG-18934 )

There is another KDE bug which seems to have the same root cause:
https://bugs.kde.org/show_bug.cgi?id=252602

So far as I can see, this really needs to be fixed in QProcess.
The fix would, I guess, make qt_create_pipe return an integer, and
then have startProcess check the return value,
set processError and abort.

Can this be done in a reasonable timeframe? Does anyone know how to submit
Qt patches?

Simeon

[Attachment #5 (text/html)]

( 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/qproc \
ess_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&#39;t check errors properly.<br><br>The longer \
version:<br><br>When QProcess-&gt;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&#39;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>



_______________________________________________
Nepomuk mailing list
Nepomuk@kde.org
https://mail.kde.org/mailman/listinfo/nepomuk


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic