Problem with KProcess and KProcess::Block

Andreas Pakulat apaku at gmx.de
Wed Nov 8 21:29:08 UTC 2006


Hi,

as discussed on irc I send a patch for kdevelop/buildtools/qmake that
adds the new class and a adds its usage to scope.cpp.

The problem is that the forked process never really exits, a zombie
process is created. It doesn't matter if I use a shell or not (though
qmake doesn't run without a shell) or if I use qmake or just kcalc as
application.

Andreas

-- 
You will always have good luck in your personal affairs.
-------------- next part --------------
diff -u -x.svn -xMakefile.in -Nur kdevelop_org/buildtools/qmake/Makefile.am kdevelop/buildtools/qmake/Makefile.am
--- kdevelop_org/buildtools/qmake/Makefile.am	2006-11-07 22:17:27.000000000 +0100
+++ kdevelop/buildtools/qmake/Makefile.am	2006-11-08 15:41:17.000000000 +0100
@@ -15,12 +15,12 @@
 	$(top_builddir)/buildtools/lib/base/libkdevbuildbase.la \
 	$(top_builddir)/buildtools/lib/parsers/qmake/libkdevqmakeparser.la
 
-libkdevtrollproject_la_SOURCES = projectconfigurationdlgbase.ui \
-	newwidgetdlgbase.ui newwidgetdlg.cpp projectconfigurationdlg.cpp trollprojectpart.cpp \
-	trollprojectwidget.cpp choosesubprojectdlgbase.ui choosesubprojectdlg.cpp trolllistview.cpp \
-	pathutil.cpp scope.cpp qmakescopeitem.cpp qmakeoptionswidgetbase.ui \
-	qmakeoptionswidget.cpp createscopedlgbase.ui createscopedlg.cpp disablesubprojectdlgbase.ui \
-	disablesubprojectdlg.cpp
+libkdevtrollproject_la_SOURCES = choosesubprojectdlg.cpp \
+	choosesubprojectdlgbase.ui createscopedlg.cpp createscopedlgbase.ui disablesubprojectdlg.cpp \
+	disablesubprojectdlgbase.ui newwidgetdlg.cpp newwidgetdlgbase.ui pathutil.cpp \
+	projectconfigurationdlg.cpp projectconfigurationdlgbase.ui qmakedefaultopts.cpp \
+	qmakeoptionswidget.cpp qmakeoptionswidgetbase.ui qmakescopeitem.cpp scope.cpp \
+	trolllistview.cpp trollprojectpart.cpp trollprojectwidget.cpp
 
 
 METASOURCES = AUTO
@@ -30,5 +30,5 @@
 
 rcdir = $(kde_datadir)/kdevtrollproject
 rc_DATA = kdevtrollproject.rc
-noinst_HEADERS = trolllistview.h qmakescopeitem.h qmakeoptionswidget.h \
-	createscopedlg.h disablesubprojectdlg.h
+noinst_HEADERS = createscopedlg.h disablesubprojectdlg.h qmakedefaultopts.h \
+	qmakeoptionswidget.h qmakescopeitem.h trolllistview.h
diff -u -x.svn -xMakefile.in -Nur kdevelop_org/buildtools/qmake/qmakedefaultopts.cpp kdevelop/buildtools/qmake/qmakedefaultopts.cpp
--- kdevelop_org/buildtools/qmake/qmakedefaultopts.cpp	1970-01-01 01:00:00.000000000 +0100
+++ kdevelop/buildtools/qmake/qmakedefaultopts.cpp	2006-11-08 22:21:06.000000000 +0100
@@ -0,0 +1,114 @@
+/***************************************************************************
+*   Copyright (C) 2006 by Andreas Pakulat                                 *
+*   apaku at gmx.de                                                          *
+*                                                                         *
+*   This program is free software; you can redistribute it and/or modify  *
+*   it under the terms of the GNU General Public License as published by  *
+*   the Free Software Foundation; either version 2 of the License, or     *
+*   (at your option) any later version.                                   *
+*                                                                         *
+***************************************************************************/
+
+#include "qmakedefaultopts.h"
+
+#include <kprocess.h>
+#include <kdebug.h>
+
+#include <qdir.h>
+#include <qregexp.h>
+#include <qprocess.h>
+
+#include "trollprojectpart.h"
+
+QMakeDefaultOpts::QMakeDefaultOpts( QObject *parent, const char *name )
+    : QObject(parent, name), qmakefile(0), makefile(0), proc(0)
+{
+
+}
+
+void QMakeDefaultOpts::readVariables( const QString& qtdir, const QString& projdir )
+{
+    makefile = new KTempFile(projdir+"/", ".mf");
+    qmakefile = new KTempFile("/tmp/", ".pro");
+    if( makefile->status() == 0 && qmakefile->status() == 0  )
+    {
+        if( !makefile->close() )
+            kdDebug(9024) << "Couldn't close makefile" << endl;
+        if( !qmakefile->close() )
+            kdDebug(9024) << "Couldn't close makefile" << endl;
+        QString qmakebin = qtdir + QString( QChar( QDir::separator() ) ) + "bin" + QString( QChar( QDir::separator() ) ) + "qmake";
+
+        if( proc )
+            delete proc;
+
+        proc = new KProcess(this);
+        proc->setUseShell(true);
+        *proc << KProcess::quote( qmakebin ) << "-d";
+        proc->setWorkingDirectory( projdir );
+        *proc << "-o" << KProcess::quote( makefile->name() ) << KProcess::quote( qmakefile->name() );
+        connect( proc, SIGNAL( processExited( KProcess* ) ),
+                 this, SLOT( slotQMakeFinished( KProcess* ) ) );
+        connect( proc, SIGNAL( receivedStderr( KProcess*, char*, int ) ),
+                 this, SLOT( slotStderr( KProcess*, char*, int ) ) );
+        kdDebug(9024) << "Running process: " << proc->args() << endl;
+        proc->start( KProcess::Block, KProcess::Stderr );
+        if( !proc->normalExit() || proc->exitStatus() != 0 )
+            kdDebug(9024) << "Couldn't start process for qmake vars" << proc->normalExit() << proc->coreDumped() << proc->exitStatus() << endl;
+
+    }
+}
+
+QMakeDefaultOpts::~QMakeDefaultOpts()
+{
+    delete proc;
+    proc = 0;
+    delete makefile;
+    makefile = 0;
+    delete qmakefile;
+    qmakefile = 0;
+    m_variables.clear();
+}
+
+void QMakeDefaultOpts::slotStderr( KProcess* , char* buf, int len )
+{
+    kdDebug(9024) << "error slot" << endl;
+    QString buffer = QString::fromLocal8Bit(buf, len);
+    QStringList lines = QStringList::split("\n", buffer);
+    for( QStringList::iterator it = lines.begin(); it != lines.end(); ++it )
+    {
+        QRegExp re("DEBUG 1: ([^ =:]+) === (.*)");
+        if( re.exactMatch(*it) )
+        {
+            QString var = re.cap(1);
+            QStringList values = QStringList::split(" :: ", re.cap(2));
+            m_variables[var] = values;
+        }
+    }
+}
+
+void QMakeDefaultOpts::slotQMakeFinished( KProcess* )
+{
+    makefile->unlink();
+    qmakefile->unlink();
+    proc->closeAll();
+    delete proc;
+    proc = 0;
+}
+
+QStringList QMakeDefaultOpts::variableValues( const QString& var ) const
+{
+    QStringList result;
+    if( m_variables.contains(var) )
+        result = m_variables[var];
+    return result;
+}
+
+QStringList QMakeDefaultOpts::variables() const
+{
+    return m_variables.keys();
+}
+
+#include "qmakedefaultopts.moc"
+
+
+// kate: space-indent on; indent-width 4; tab-width 4; replace-tabs on
diff -u -x.svn -xMakefile.in -Nur kdevelop_org/buildtools/qmake/qmakedefaultopts.h kdevelop/buildtools/qmake/qmakedefaultopts.h
--- kdevelop_org/buildtools/qmake/qmakedefaultopts.h	1970-01-01 01:00:00.000000000 +0100
+++ kdevelop/buildtools/qmake/qmakedefaultopts.h	2006-11-08 22:07:20.000000000 +0100
@@ -0,0 +1,49 @@
+/***************************************************************************
+*   Copyright (C) 2006 by Andreas Pakulat                                 *
+*   apaku at gmx.de                                                          *
+*                                                                         *
+*   This program is free software; you can redistribute it and/or modify  *
+*   it under the terms of the GNU General Public License as published by  *
+*   the Free Software Foundation; either version 2 of the License, or     *
+*   (at your option) any later version.                                   *
+*                                                                         *
+***************************************************************************/
+
+#ifndef QMAKEDEFAULTOPTS_H
+#define QMAKEDEFAULTOPTS_H
+
+#include <qobject.h>
+#include <qmap.h>
+#include <ktempfile.h>
+
+class KProcess;
+class TrollProjectPart;
+
+class QMakeDefaultOpts : public QObject
+{
+    Q_OBJECT
+public:
+    QMakeDefaultOpts( QObject *parent = 0, const char *name = 0 );
+
+    ~QMakeDefaultOpts();
+
+    void readVariables( const QString& qtdir, const QString& projdir );
+
+    QStringList variableValues( const QString& ) const;
+    QStringList variables() const;
+
+private slots:
+    void slotStderr( KProcess*, char*, int );
+    void slotQMakeFinished( KProcess* );
+
+private:
+    QMap<QString, QStringList> m_variables;
+    KTempFile* qmakefile;
+    KTempFile* makefile;
+    KProcess* proc;
+};
+
+#endif
+
+
+// kate: space-indent on; indent-width 4; tab-width 4; replace-tabs on
diff -u -x.svn -xMakefile.in -Nur kdevelop_org/buildtools/qmake/scope.cpp kdevelop/buildtools/qmake/scope.cpp
--- kdevelop_org/buildtools/qmake/scope.cpp	2006-11-08 22:23:13.000000000 +0100
+++ kdevelop/buildtools/qmake/scope.cpp	2006-11-08 22:27:31.000000000 +0100
@@ -23,6 +23,7 @@
 
 #include "pathutil.h"
 #include "trollprojectpart.h"
+#include "qmakedefaultopts.h"
 
 const QStringList Scope::KnownVariables = QStringList() << "QT" << "CONFIG" << "TEMPLATE" << "SUBDIRS" << "VERSION" << "LIBS" << "target.path" << "INSTALLS" << "MAKEFILE" << "TARGETDEPS" << "INCLUDEPATH" << "TARGET" << "DESTDIR" << "DEFINES" << "QMAKE_CXXFLAGS_DEBUG" << "QMAKE_CXXFLAGS_RELEASE" << "OBJECTS_DIR" << "UI_DIR" << "MOC_DIR" << "IDL_COMPILER" << "IDL_OPTIONS" << "RCC_DIR" << "IDLS" << "RESOURCES" << "IMAGES" << "LEXSOURCES" << "DISTFILES" << "YACCSOURCES" << "TRANSLATIONS" << "HEADERS" << "SOURCES" << "INTERFACES" << "FORMS" ;
 
@@ -31,6 +32,12 @@
 Scope::Scope( const QString &filename, TrollProjectPart* part )
     : m_root( 0 ), m_incast( 0 ), m_parent( 0 ), m_num(0), m_isEnabled( true ), m_part(part)
 {
+    // The following should work, but always leaves a zombie process when used on my system.
+    QMakeDefaultOpts m_defaultopts;
+    m_defaultopts.readVariables( DomUtil::readEntry( *m_part->projectDom(), "/kdevcppsupport/qt/root", "" ), QFileInfo( filename ).dirPath( true ) );
+    QStringList vars = m_defaultopts.variables();
+    for( QStringList::const_iterator it = vars.begin(); it != vars.end(); ++it )
+        kdDebug(9024) << *it << "===" << m_defaultopts.variableValues( *it ).join( "::" ) << endl;
     if ( !loadFromFile( filename ) )
     {
         if( !QFileInfo( filename ).exists() )
diff -u -x.svn -xMakefile.in -Nur kdevelop_org/buildtools/qmake/scope.h kdevelop/buildtools/qmake/scope.h
--- kdevelop_org/buildtools/qmake/scope.h	2006-11-07 22:17:27.000000000 +0100
+++ kdevelop/buildtools/qmake/scope.h	2006-11-08 22:05:25.000000000 +0100
@@ -17,26 +17,12 @@
 #include <qmap.h>
 
 #include "qmakeast.h"
+#include "qmakedefaultopts.h"
 
 #ifdef DEBUG
 #include "qmakeastvisitor.h"
 #endif
 
-/*
- * TODO:
- * - Ask adymo again about variables, we can't just always put a new assignment at the end of the file, because that clutters the file after a few open/save cycles
-        -> recursively check for other assignments to the variable (into scopes)
- * - talk to adymo about the possibility to add a way to parse only part of a QMake project file in case the include-creation code doesn't work
-        -> see mail, find out wether the proposed function could be better, flex reading from memory...
- * - talk to adymo why function calls are "automatically" scopes and not function calls
-        -> line 243 in parser, in init() do special handling of FunctionCall's, make a FunctionScope+AssignmentAST out of it, or use http://rafb.net/paste/results/EE43DN82.html patch
- * - talk to adymo about memory handling in AST's, do they delete their children upon deletion?
-        -> deletion of childs.
- * - talk to adymo about how to handle unparsable file's - overwrite or set m_root to 0?
-        -> to rare to handle specially.
- * - Handle multiple function calls with different arguments
- */
-
 class Scope;
 class TrollProjectPart;
 
@@ -256,6 +242,7 @@
     unsigned int m_num;
     bool m_isEnabled;
     TrollProjectPart* m_part;
+
 #ifdef DEBUG
     class PrintAST : QMake::ASTVisitor
     {
@@ -289,6 +276,7 @@
         QString getIndent();
         QString replaceWs(QString);
         int indent;
+
     };
 #endif
 
diff -u -x.svn -xMakefile.in -Nur kdevelop_org/buildtools/qmake/trollprojectpart.h kdevelop/buildtools/qmake/trollprojectpart.h
--- kdevelop_org/buildtools/qmake/trollprojectpart.h	2006-11-07 22:17:27.000000000 +0100
+++ kdevelop/buildtools/qmake/trollprojectpart.h	2006-11-08 15:36:06.000000000 +0100
@@ -26,6 +26,7 @@
 class KDialogBase;
 class TrollProjectWidget;
 class KDirWatch;
+class QMakeDefaultOpts;
 
 class TrollProjectPart : public KDevBuildTool
 {
@@ -95,6 +96,7 @@
 
     friend class TrollProjectWidget;
     friend class ProjectRunOptionsDlg;
+    friend class QMakeDefaultOpts;
 };
 
 #endif


More information about the KDevelop-devel mailing list