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