diff --git a/repos/libports/lib/mk/qt5_core.mk b/repos/libports/lib/mk/qt5_core.mk index eea1c01efa..ab5851f5a5 100644 --- a/repos/libports/lib/mk/qt5_core.mk +++ b/repos/libports/lib/mk/qt5_core.mk @@ -8,8 +8,7 @@ CC_WARN = -Wno-unused-but-set-variable -Wno-deprecated-declarations include $(REP_DIR)/lib/mk/qt5_core_generated.inc # add Genode-specific sources -QT_SOURCES += qprocess_genode.cpp \ - qthread_genode.cpp +QT_SOURCES += qthread_genode.cpp # remove unsupported UNIX-specific files QT_SOURCES_FILTER_OUT = \ @@ -35,4 +34,4 @@ INC_DIR += $(REP_DIR)/include/qt5/qtbase/QtCore/private \ $(QT5_CONTRIB_DIR)/qtbase/include/QtCore/$(QT_VERSION)/QtCore \ $(QT5_CONTRIB_DIR)/qtbase/include/QtCore/$(QT_VERSION)/QtCore/private -LIBS += qt5_host_tools launchpad zlib icu libc libm alarm libc_pipe pthread +LIBS += qt5_host_tools zlib icu libc libm alarm libc_pipe pthread diff --git a/repos/libports/ports/qt5.hash b/repos/libports/ports/qt5.hash index e9cd58aa9a..4abb9119ca 100644 --- a/repos/libports/ports/qt5.hash +++ b/repos/libports/ports/qt5.hash @@ -1 +1 @@ -8c8f232dcaa82e015b4f25f4fa99e7c7eeecc128 +ad39740935637ba07e227c2faf8f69891233a5ae diff --git a/repos/libports/src/app/qt5/qt_launchpad/target.mk b/repos/libports/src/app/qt5/qt_launchpad/target.mk index 1f035e42bf..e02f81d7f5 100644 --- a/repos/libports/src/app/qt5/qt_launchpad/target.mk +++ b/repos/libports/src/app/qt5/qt_launchpad/target.mk @@ -5,3 +5,5 @@ QT5_REP_DIR := $(realpath $(dir $(QT5_REP_DIR))../..) include $(QT5_REP_DIR)/src/app/qt5/tmpl/target_defaults.inc include $(QT5_REP_DIR)/src/app/qt5/tmpl/target_final.inc + +LIBS += launchpad diff --git a/repos/libports/src/lib/qt5/patches/qt5_configuration.patch b/repos/libports/src/lib/qt5/patches/qt5_configuration.patch index 85d82ae67a..abd9b08ed5 100644 --- a/repos/libports/src/lib/qt5/patches/qt5_configuration.patch +++ b/repos/libports/src/lib/qt5/patches/qt5_configuration.patch @@ -262,7 +262,7 @@ index 0000000..4d2c580 +#endif // QPLATFORMDEFS_H diff --git a/qtbase/src/corelib/global/qconfig-genode.h b/qtbase/src/corelib/global/qconfig-genode.h new file mode 100644 -index 0000000..6227a0c +index 0000000..681af14 --- /dev/null +++ b/qtbase/src/corelib/global/qconfig-genode.h @@ -0,0 +1,546 @@ @@ -322,9 +322,9 @@ index 0000000..6227a0c +//#ifndef QT_NO_FILESYSTEMMODEL +//# define QT_NO_FILESYSTEMMODEL +//#endif -+//#ifndef QT_NO_PROCESS -+//# define QT_NO_PROCESS -+//#endif ++#ifndef QT_NO_PROCESS ++# define QT_NO_PROCESS ++#endif +//#ifndef QT_NO_TEMPORARYFILE +//# define QT_NO_TEMPORARYFILE +//#endif diff --git a/repos/libports/src/lib/qt5/patches/qt5_qtbase_genode.patch b/repos/libports/src/lib/qt5/patches/qt5_qtbase_genode.patch index f35d6f695d..cbd99d98a6 100644 --- a/repos/libports/src/lib/qt5/patches/qt5_qtbase_genode.patch +++ b/repos/libports/src/lib/qt5/patches/qt5_qtbase_genode.patch @@ -7,22 +7,20 @@ Genode-specific adaptations qtbase/src/corelib/codecs/qtextcodec.cpp | 4 + qtbase/src/corelib/global/qlogging.cpp | 6 ++ qtbase/src/corelib/global/qsystemdetection.h | 5 +- - qtbase/src/corelib/io/qprocess.cpp | 64 ++++++++++++++++++++ - qtbase/src/corelib/io/qprocess_p.h | 45 ++++++++++++++ qtbase/src/corelib/io/qresource.cpp | 2 - qtbase/src/corelib/kernel/qcoreapplication.cpp | 2 - - .../src/corelib/kernel/qeventdispatcher_unix.cpp | 14 ++++ + .../src/corelib/kernel/qeventdispatcher_unix.cpp | 14 +++++ qtbase/src/corelib/kernel/qtranslator.cpp | 2 - qtbase/src/corelib/thread/qthread.cpp | 5 +- - qtbase/src/corelib/thread/qthread_p.h | 55 +++++++++++++++++ + qtbase/src/corelib/thread/qthread_p.h | 55 ++++++++++++++++++++ qtbase/src/corelib/tools/qdatetime.cpp | 15 +++++ qtbase/src/gui/image/qxpmhandler.cpp | 8 +++ .../network/access/qnetworkaccessfilebackend.cpp | 5 ++ qtbase/src/network/kernel/qhostinfo.cpp | 5 ++ - qtbase/src/network/kernel/qhostinfo_unix.cpp | 7 ++ + qtbase/src/network/kernel/qhostinfo_unix.cpp | 7 ++- qtbase/src/widgets/dialogs/qfiledialog.cpp | 2 - - qtbase/src/widgets/styles/qstylefactory.cpp | 7 ++ - 18 files changed, 245 insertions(+), 8 deletions(-) + qtbase/src/widgets/styles/qstylefactory.cpp | 7 +++ + 16 files changed, 137 insertions(+), 7 deletions(-) diff --git a/qtbase/src/corelib/codecs/qtextcodec.cpp b/qtbase/src/corelib/codecs/qtextcodec.cpp index 1cedd3a..646be07 100644 @@ -87,165 +85,6 @@ index cb55fa8..7d5c507 100644 # define Q_OS_DARWIN # define Q_OS_BSD4 # ifdef __LP64__ -diff --git a/qtbase/src/corelib/io/qprocess.cpp b/qtbase/src/corelib/io/qprocess.cpp -index b1861d8..b1cbf57 100644 ---- a/qtbase/src/corelib/io/qprocess.cpp -+++ b/qtbase/src/corelib/io/qprocess.cpp -@@ -98,6 +98,11 @@ QT_END_NAMESPACE - #include <qwineventnotifier.h> - #endif - -+#ifdef Q_OS_GENODE -+#include <rom_session/connection.h> -+#include <util/xml_node.h> -+#endif -+ - #ifndef QT_NO_PROCESS - - QT_BEGIN_NAMESPACE -@@ -789,6 +794,65 @@ QProcessPrivate::QProcessPrivate() - #ifdef Q_OS_UNIX - serial = 0; - #endif -+#ifdef Q_OS_GENODE -+ launchpad_child = 0; -+ -+ /* request config file from ROM service */ -+ Genode::Rom_connection rom("config"); -+ rom.on_destruction(Genode::Rom_connection::KEEP_OPEN); -+ void *addr; -+ try { -+ addr = Genode::env()->rm_session()->attach(rom.dataspace()); -+ } catch(Genode::Parent::Service_denied) { -+ qWarning("Error: Couldn't open config file."); -+ return; -+ } -+ -+ /* -+ * The XML data of a valid config file starts with -+ * a <config> tag. -+ */ -+ Genode::Xml_node config_node((const char *)addr); -+ -+ if (!config_node.has_type("config")) { -+ qWarning("Error: Root node of config file is not a <config> tag."); -+ return; -+ } -+ -+ /* -+ * Iterate through all entries of the config file and start -+ * children as specified. -+ */ -+ for (int i = 0; i < config_node.num_sub_nodes(); i++) { -+ Genode::Xml_node program_node = config_node.sub_node(i); -+ if (program_node.has_type("program")) { -+ -+ /* add filename and ram_quota to ram_quota_hash */ -+ char filename[32]; -+ try { -+ program_node.sub_node("filename").value(filename, sizeof(filename)); -+ } catch (Genode::Xml_node::Nonexistent_sub_node) { -+ qWarning("Warning: Missing valid <filename> in config-file entry."); -+ return; -+ } -+ -+ size_t ram_quota = 0; -+ try { -+ program_node.sub_node("ram_quota").value(&ram_quota); -+ } catch (Genode::Xml_node::Nonexistent_sub_node) { -+ qWarning("Warning: Missing valid <ram_quota> in config-file entry."); -+ return; -+ } -+ -+ ram_quota_hash()->insert(QString(filename), ram_quota); -+ } else { -+ char buf[32]; -+ program_node.type_name(buf, sizeof(buf)); -+ qWarning("Warning: Ignoring unsupported tag <%s>.", buf); -+ } -+ } -+ -+#endif - } - - /*! -diff --git a/qtbase/src/corelib/io/qprocess_p.h b/qtbase/src/corelib/io/qprocess_p.h -index 2a2cc9f..2173aa0 100644 ---- a/qtbase/src/corelib/io/qprocess_p.h -+++ b/qtbase/src/corelib/io/qprocess_p.h -@@ -74,6 +74,11 @@ typedef int Q_PIPE; - - #ifndef QT_NO_PROCESS - -+#ifdef Q_OS_GENODE -+#include <base/env.h> -+#include <launchpad/launchpad.h> -+#endif -+ - QT_BEGIN_NAMESPACE - - class QSocketNotifier; -@@ -235,6 +240,28 @@ template<> Q_INLINE_TEMPLATE void QSharedDataPointer<QProcessEnvironmentPrivate> - d = x; - } - -+#ifdef Q_OS_GENODE -+ -+class QProcess_launchpad : public Launchpad -+{ -+public: -+ QProcess_launchpad(unsigned long initial_quota) : Launchpad(initial_quota) {} -+ -+ virtual void quota(unsigned long quota) {} -+ -+ virtual void add_launcher(const char *filename, -+ unsigned long default_quota) {} -+ -+ virtual void add_child(const char *unique_name, -+ unsigned long quota, -+ Launchpad_child *launchpad_child, -+ Genode::Allocator *alloc) {} -+ -+ virtual void remove_child(const char *name, Genode::Allocator *alloc) {} -+}; -+ -+#endif -+ - class QProcessPrivate : public QIODevicePrivate - { - public: -@@ -347,7 +374,7 @@ public: - #endif - - void startProcess(); --#if defined(Q_OS_UNIX) && !defined(Q_OS_QNX) -+#if defined(Q_OS_UNIX) && !defined(Q_OS_QNX) && !defined(Q_OS_GENODE) - void execChild(const char *workingDirectory, char **path, char **argv, char **envp); - #elif defined(Q_OS_QNX) - pid_t spawnChild(const char *workingDirectory, char **argv, char **envp); -@@ -375,6 +402,22 @@ public: - int serial; - #endif - -+#ifdef Q_OS_GENODE -+ static QProcess_launchpad *launchpad() -+ { -+ static QProcess_launchpad _launchpad(Genode::env()->ram_session()->quota()); -+ return &_launchpad; -+ } -+ -+ static QHash<QString, size_t> *ram_quota_hash() -+ { -+ static QHash<QString, size_t> _ram_quota_hash; -+ return &_ram_quota_hash; -+ } -+ -+ Launchpad_child *launchpad_child; -+#endif -+ - bool waitForStarted(int msecs = 30000); - bool waitForReadyRead(int msecs = 30000); - bool waitForBytesWritten(int msecs = 30000); diff --git a/qtbase/src/corelib/io/qresource.cpp b/qtbase/src/corelib/io/qresource.cpp index 04ec81e..2211125 100644 --- a/qtbase/src/corelib/io/qresource.cpp diff --git a/repos/libports/src/lib/qt5/qtbase/src/corelib/io/qprocess_genode.cpp b/repos/libports/src/lib/qt5/qtbase/src/corelib/io/qprocess_genode.cpp deleted file mode 100644 index 1446b9c01a..0000000000 --- a/repos/libports/src/lib/qt5/qtbase/src/corelib/io/qprocess_genode.cpp +++ /dev/null @@ -1,1595 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** This file is part of the QtCore module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -//#define QPROCESS_DEBUG -#include "qdebug.h" - -#ifndef QT_NO_PROCESS - -#ifndef Q_OS_GENODE -#if defined QPROCESS_DEBUG -#include "qstring.h" -#include <ctype.h> - - -/* - Returns a human readable representation of the first \a len - characters in \a data. -*/ -QT_BEGIN_NAMESPACE -static QByteArray qt_prettyDebug(const char *data, int len, int maxSize) -{ - if (!data) return "(null)"; - QByteArray out; - for (int i = 0; i < len; ++i) { - char c = data[i]; - if (isprint(c)) { - out += c; - } else switch (c) { - case '\n': out += "\\n"; break; - case '\r': out += "\\r"; break; - case '\t': out += "\\t"; break; - default: - QString tmp; - tmp.sprintf("\\%o", c); - out += tmp.toLatin1(); - } - } - - if (len < maxSize) - out += "..."; - - return out; -} -QT_END_NAMESPACE -#endif -#endif /* Q_OS_GENODE */ - -#include "qplatformdefs.h" - -#include "qprocess.h" -#include "qprocess_p.h" -#include "private/qcore_unix_p.h" - -#ifdef Q_OS_MAC -#include <private/qcore_mac_p.h> -#endif - -#include <private/qcoreapplication_p.h> -#include <private/qthread_p.h> -#include <qfile.h> -#include <qfileinfo.h> -#include <qlist.h> -#include <qhash.h> -#include <qmutex.h> -#include <qsemaphore.h> -#include <qsocketnotifier.h> -#include <qthread.h> -#include <qelapsedtimer.h> - -#include <errno.h> -#include <stdlib.h> -#include <string.h> -#ifdef Q_OS_QNX -#include "qvarlengtharray.h" - -#include <spawn.h> -#include <sys/neutrino.h> -#endif - -QT_BEGIN_NAMESPACE - -// POSIX requires PIPE_BUF to be 512 or larger -// so we will use 512 -static const int errorBufferMax = 512; -#ifndef Q_OS_GENODE -static int qt_qprocess_deadChild_pipe[2]; -static struct sigaction qt_sa_old_sigchld_handler; -static void qt_sa_sigchld_handler(int signum) -{ - qt_safe_write(qt_qprocess_deadChild_pipe[1], "", 1); -#if defined (QPROCESS_DEBUG) - fprintf(stderr, "*** SIGCHLD\n"); -#endif - - // load it as volatile - void (*oldAction)(int) = ((volatile struct sigaction *)&qt_sa_old_sigchld_handler)->sa_handler; - if (oldAction && oldAction != SIG_IGN) - oldAction(signum); -} -#endif /* Q_OS_GENODE */ - -static inline void add_fd(int &nfds, int fd, fd_set *fdset) -{ - FD_SET(fd, fdset); - if ((fd) > nfds) - nfds = fd; -} - -struct QProcessInfo { - QProcess *process; - int deathPipe; - int exitResult; - pid_t pid; - int serialNumber; -}; - -#ifndef Q_OS_GENODE -class QProcessManager : public QThread -{ - Q_OBJECT -public: - QProcessManager(); - ~QProcessManager(); - - void run(); - void catchDeadChildren(); - void add(pid_t pid, QProcess *process); - void remove(QProcess *process); - void lock(); - void unlock(); - -private: - QMutex mutex; - QHash<int, QProcessInfo *> children; -}; - - -static QProcessManager *processManagerInstance = 0; - -static QProcessManager *processManager() -{ - // The constructor of QProcessManager should be called only once - // so we cannot use Q_GLOBAL_STATIC directly for QProcessManager - static QBasicMutex processManagerGlobalMutex; - QMutexLocker locker(&processManagerGlobalMutex); - - if (!processManagerInstance) - new QProcessManager; - - Q_ASSERT(processManagerInstance); - return processManagerInstance; -} - -QProcessManager::QProcessManager() -{ -#if defined (QPROCESS_DEBUG) - qDebug() << "QProcessManager::QProcessManager()"; -#endif - // initialize the dead child pipe and make it non-blocking. in the - // extremely unlikely event that the pipe fills up, we do not under any - // circumstances want to block. - qt_safe_pipe(qt_qprocess_deadChild_pipe, O_NONBLOCK); - - // set up the SIGCHLD handler, which writes a single byte to the dead - // child pipe every time a child dies. - struct sigaction action; - memset(&action, 0, sizeof(action)); - action.sa_handler = qt_sa_sigchld_handler; - action.sa_flags = SA_NOCLDSTOP; - ::sigaction(SIGCHLD, &action, &qt_sa_old_sigchld_handler); - - processManagerInstance = this; -} - -QProcessManager::~QProcessManager() -{ - // notify the thread that we're shutting down. - qt_safe_write(qt_qprocess_deadChild_pipe[1], "@", 1); - qt_safe_close(qt_qprocess_deadChild_pipe[1]); - wait(); - - // on certain unixes, closing the reading end of the pipe will cause - // select in run() to block forever, rather than return with EBADF. - qt_safe_close(qt_qprocess_deadChild_pipe[0]); - - qt_qprocess_deadChild_pipe[0] = -1; - qt_qprocess_deadChild_pipe[1] = -1; - - qDeleteAll(children.values()); - children.clear(); - - struct sigaction currentAction; - ::sigaction(SIGCHLD, 0, ¤tAction); - if (currentAction.sa_handler == qt_sa_sigchld_handler) { - ::sigaction(SIGCHLD, &qt_sa_old_sigchld_handler, 0); - } - - processManagerInstance = 0; -} - -void QProcessManager::run() -{ - forever { - fd_set readset; - FD_ZERO(&readset); - FD_SET(qt_qprocess_deadChild_pipe[0], &readset); - -#if defined (QPROCESS_DEBUG) - qDebug() << "QProcessManager::run() waiting for children to die"; -#endif - - // block forever, or until activity is detected on the dead child - // pipe. the only other peers are the SIGCHLD signal handler, and the - // QProcessManager destructor. - int nselect = select(qt_qprocess_deadChild_pipe[0] + 1, &readset, 0, 0, 0); - if (nselect < 0) { - if (errno == EINTR) - continue; - break; - } - - // empty only one byte from the pipe, even though several SIGCHLD - // signals may have been delivered in the meantime, to avoid race - // conditions. - char c; - if (qt_safe_read(qt_qprocess_deadChild_pipe[0], &c, 1) < 0 || c == '@') - break; - - // catch any and all children that we can. - catchDeadChildren(); - } -} - -void QProcessManager::catchDeadChildren() -{ - QMutexLocker locker(&mutex); - - // try to catch all children whose pid we have registered, and whose - // deathPipe is still valid (i.e, we have not already notified it). - QHash<int, QProcessInfo *>::Iterator it = children.begin(); - while (it != children.end()) { - // notify all children that they may have died. they need to run - // waitpid() in their own thread. - QProcessInfo *info = it.value(); - qt_safe_write(info->deathPipe, "", 1); - -#if defined (QPROCESS_DEBUG) - qDebug() << "QProcessManager::run() sending death notice to" << info->process; -#endif - ++it; - } -} - -static QBasicAtomicInt idCounter = Q_BASIC_ATOMIC_INITIALIZER(1); - -void QProcessManager::add(pid_t pid, QProcess *process) -{ -#if defined (QPROCESS_DEBUG) - qDebug() << "QProcessManager::add() adding pid" << pid << "process" << process; -#endif - - // insert a new info structure for this process - QProcessInfo *info = new QProcessInfo; - info->process = process; - info->deathPipe = process->d_func()->deathPipe[1]; - info->exitResult = 0; - info->pid = pid; - - int serial = idCounter.fetchAndAddRelaxed(1); - process->d_func()->serial = serial; - children.insert(serial, info); -} - -void QProcessManager::remove(QProcess *process) -{ - QMutexLocker locker(&mutex); - - int serial = process->d_func()->serial; - QProcessInfo *info = children.take(serial); -#if defined (QPROCESS_DEBUG) - if (info) - qDebug() << "QProcessManager::remove() removing pid" << info->pid << "process" << info->process; -#endif - delete info; -} - -void QProcessManager::lock() -{ - mutex.lock(); -} - -void QProcessManager::unlock() -{ - mutex.unlock(); -} - -static void qt_create_pipe(int *pipe) -{ - if (pipe[0] != -1) - qt_safe_close(pipe[0]); - if (pipe[1] != -1) - qt_safe_close(pipe[1]); - if (qt_safe_pipe(pipe) != 0) { - qWarning("QProcessPrivate::createPipe: Cannot create pipe %p: %s", - pipe, qPrintable(qt_error_string(errno))); - } -} -#endif /* Q_OS_GENODE */ - -void QProcessPrivate::destroyPipe(int *pipe) -{ -#ifdef Q_OS_GENODE -#if defined QPROCESS_DEBUG - qDebug() << "destroyPipe()"; -#endif -#else - if (pipe[1] != -1) { - qt_safe_close(pipe[1]); - pipe[1] = -1; - } - if (pipe[0] != -1) { - qt_safe_close(pipe[0]); - pipe[0] = -1; - } -#endif /* Q_OS_GENODE */ -} - -void QProcessPrivate::destroyChannel(Channel *channel) -{ -#ifdef Q_OS_GENODE -#if defined QPROCESS_DEBUG - qDebug() << "destroyChannel()"; -#endif -#else - destroyPipe(channel->pipe); -#endif /* Q_OS_GENODE */ -} - -/* - Create the pipes to a QProcessPrivate::Channel. - - This function must be called in order: stdin, stdout, stderr -*/ -bool QProcessPrivate::createChannel(Channel &channel) -{ -#ifdef Q_OS_GENODE -#if defined QPROCESS_DEBUG - qDebug() << "createChannel()"; -#endif -#else - Q_Q(QProcess); - - if (&channel == &stderrChannel && processChannelMode == QProcess::MergedChannels) { - channel.pipe[0] = -1; - channel.pipe[1] = -1; - return true; - } - - if (channel.type == Channel::Normal) { - // we're piping this channel to our own process - qt_create_pipe(channel.pipe); - - // create the socket notifiers - if (threadData->eventDispatcher) { - if (&channel == &stdinChannel) { - channel.notifier = new QSocketNotifier(channel.pipe[1], - QSocketNotifier::Write, q); - channel.notifier->setEnabled(false); - QObject::connect(channel.notifier, SIGNAL(activated(int)), - q, SLOT(_q_canWrite())); - } else { - channel.notifier = new QSocketNotifier(channel.pipe[0], - QSocketNotifier::Read, q); - const char *receiver; - if (&channel == &stdoutChannel) - receiver = SLOT(_q_canReadStandardOutput()); - else - receiver = SLOT(_q_canReadStandardError()); - QObject::connect(channel.notifier, SIGNAL(activated(int)), - q, receiver); - } - } - - return true; - } else if (channel.type == Channel::Redirect) { - // we're redirecting the channel to/from a file - QByteArray fname = QFile::encodeName(channel.file); - - if (&channel == &stdinChannel) { - // try to open in read-only mode - channel.pipe[1] = -1; - if ( (channel.pipe[0] = qt_safe_open(fname, O_RDONLY)) != -1) - return true; // success - - q->setErrorString(QProcess::tr("Could not open input redirection for reading")); - } else { - int mode = O_WRONLY | O_CREAT; - if (channel.append) - mode |= O_APPEND; - else - mode |= O_TRUNC; - - channel.pipe[0] = -1; - if ( (channel.pipe[1] = qt_safe_open(fname, mode, 0666)) != -1) - return true; // success - - q->setErrorString(QProcess::tr("Could not open output redirection for writing")); - } - - // could not open file - processError = QProcess::FailedToStart; - emit q->error(processError); - cleanup(); - return false; - } else { - Q_ASSERT_X(channel.process, "QProcess::start", "Internal error"); - - Channel *source; - Channel *sink; - - if (channel.type == Channel::PipeSource) { - // we are the source - source = &channel; - sink = &channel.process->stdinChannel; - - Q_ASSERT(source == &stdoutChannel); - Q_ASSERT(sink->process == this && sink->type == Channel::PipeSink); - } else { - // we are the sink; - source = &channel.process->stdoutChannel; - sink = &channel; - - Q_ASSERT(sink == &stdinChannel); - Q_ASSERT(source->process == this && source->type == Channel::PipeSource); - } - - if (source->pipe[1] != INVALID_Q_PIPE || sink->pipe[0] != INVALID_Q_PIPE) { - // already created, do nothing - return true; - } else { - Q_ASSERT(source->pipe[0] == INVALID_Q_PIPE && source->pipe[1] == INVALID_Q_PIPE); - Q_ASSERT(sink->pipe[0] == INVALID_Q_PIPE && sink->pipe[1] == INVALID_Q_PIPE); - - Q_PIPE pipe[2] = { -1, -1 }; - qt_create_pipe(pipe); - sink->pipe[0] = pipe[0]; - source->pipe[1] = pipe[1]; - - return true; - } - } -#endif /* Q_OS_GENODE */ -} - -#ifndef Q_OS_GENODE -QT_BEGIN_INCLUDE_NAMESPACE -#if defined(Q_OS_MAC) && !defined(Q_OS_IOS) -# include <crt_externs.h> -# define environ (*_NSGetEnviron()) -#else - extern char **environ; -#endif -QT_END_INCLUDE_NAMESPACE - -QProcessEnvironment QProcessEnvironment::systemEnvironment() -{ - QProcessEnvironment env; -#if !defined(Q_OS_IOS) - const char *entry; - for (int count = 0; (entry = environ[count]); ++count) { - const char *equal = strchr(entry, '='); - if (!equal) - continue; - - QByteArray name(entry, equal - entry); - QByteArray value(equal + 1); - env.d->hash.insert(QProcessEnvironmentPrivate::Key(name), - QProcessEnvironmentPrivate::Value(value)); - } -#endif - return env; -} - -static char **_q_dupEnvironment(const QProcessEnvironmentPrivate::Hash &environment, int *envc) -{ - *envc = 0; - if (environment.isEmpty()) - return 0; - - // if LD_LIBRARY_PATH exists in the current environment, but - // not in the environment list passed by the programmer, then - // copy it over. -#if defined(Q_OS_MAC) - static const char libraryPath[] = "DYLD_LIBRARY_PATH"; -#else - static const char libraryPath[] = "LD_LIBRARY_PATH"; -#endif - const QByteArray envLibraryPath = qgetenv(libraryPath); - bool needToAddLibraryPath = !envLibraryPath.isEmpty() && - !environment.contains(QProcessEnvironmentPrivate::Key(QByteArray(libraryPath))); - - char **envp = new char *[environment.count() + 2]; - envp[environment.count()] = 0; - envp[environment.count() + 1] = 0; - - QProcessEnvironmentPrivate::Hash::ConstIterator it = environment.constBegin(); - const QProcessEnvironmentPrivate::Hash::ConstIterator end = environment.constEnd(); - for ( ; it != end; ++it) { - QByteArray key = it.key().key; - QByteArray value = it.value().bytes(); - key.reserve(key.length() + 1 + value.length()); - key.append('='); - key.append(value); - - envp[(*envc)++] = ::strdup(key.constData()); - } - - if (needToAddLibraryPath) - envp[(*envc)++] = ::strdup(QByteArray(QByteArray(libraryPath) + '=' + - envLibraryPath).constData()); - return envp; -} -#endif /* Q_OS_GENODE */ - -void QProcessPrivate::startProcess() -{ - Q_Q(QProcess); - -#if defined (QPROCESS_DEBUG) - qDebug("QProcessPrivate::startProcess()"); -#endif - -#ifndef Q_OS_GENODE - processManager()->start(); - - // Initialize pipes - if (!createChannel(stdinChannel) || - !createChannel(stdoutChannel) || - !createChannel(stderrChannel)) - return; - qt_create_pipe(childStartedPipe); - qt_create_pipe(deathPipe); - - if (threadData->eventDispatcher) { - startupSocketNotifier = new QSocketNotifier(childStartedPipe[0], - QSocketNotifier::Read, q); - QObject::connect(startupSocketNotifier, SIGNAL(activated(int)), - q, SLOT(_q_startupNotification())); - - deathNotifier = new QSocketNotifier(deathPipe[0], - QSocketNotifier::Read, q); - QObject::connect(deathNotifier, SIGNAL(activated(int)), - q, SLOT(_q_processDied())); - } -#endif /* Q_OS_GENODE */ - - // Start the process (platform dependent) - q->setProcessState(QProcess::Starting); - -#ifdef Q_OS_GENODE - launchpad_child = launchpad()->start_child(program.toLocal8Bit().constData(), - ram_quota_hash()->value(program), - Genode::Dataspace_capability()); - if (launchpad_child) { - _q_startupNotification(); - } -#else - // Create argument list with right number of elements, and set the final - // one to 0. - char **argv = new char *[arguments.count() + 2]; - argv[arguments.count() + 1] = 0; - - // Encode the program name. - QByteArray encodedProgramName = QFile::encodeName(program); -#ifdef Q_OS_MAC - // allow invoking of .app bundles on the Mac. - QFileInfo fileInfo(program); - if (encodedProgramName.endsWith(".app") && fileInfo.isDir()) { - QCFType<CFURLRef> url = CFURLCreateWithFileSystemPath(0, - QCFString(fileInfo.absoluteFilePath()), - kCFURLPOSIXPathStyle, true); - { - // CFBundle is not reentrant, since CFBundleCreate might return a reference - // to a cached bundle object. Protect the bundle calls with a mutex lock. - static QBasicMutex cfbundleMutex; - QMutexLocker lock(&cfbundleMutex); - QCFType<CFBundleRef> bundle = CFBundleCreate(0, url); - url = CFBundleCopyExecutableURL(bundle); - } - if (url) { - QCFString str = CFURLCopyFileSystemPath(url, kCFURLPOSIXPathStyle); - encodedProgramName += "/Contents/MacOS/" + QCFString::toQString(str).toUtf8(); - } - } -#endif - - // Add the program name to the argument list. - char *dupProgramName = ::strdup(encodedProgramName.constData()); - argv[0] = dupProgramName; - - // Add every argument to the list - for (int i = 0; i < arguments.count(); ++i) - argv[i + 1] = ::strdup(QFile::encodeName(arguments.at(i)).constData()); - - // Duplicate the environment. - int envc = 0; - char **envp = 0; - if (environment.d.constData()) - envp = _q_dupEnvironment(environment.d.constData()->hash, &envc); - - // Encode the working directory if it's non-empty, otherwise just pass 0. - const char *workingDirPtr = 0; - QByteArray encodedWorkingDirectory; - if (!workingDirectory.isEmpty()) { - encodedWorkingDirectory = QFile::encodeName(workingDirectory); - workingDirPtr = encodedWorkingDirectory.constData(); - } - - // If the program does not specify a path, generate a list of possible - // locations for the binary using the PATH environment variable. - char **path = 0; - int pathc = 0; - if (!program.contains(QLatin1Char('/'))) { - const QString pathEnv = QString::fromLocal8Bit(::getenv("PATH")); - if (!pathEnv.isEmpty()) { - QStringList pathEntries = pathEnv.split(QLatin1Char(':'), QString::SkipEmptyParts); - if (!pathEntries.isEmpty()) { - pathc = pathEntries.size(); - path = new char *[pathc + 1]; - path[pathc] = 0; - - for (int k = 0; k < pathEntries.size(); ++k) { - QByteArray tmp = QFile::encodeName(pathEntries.at(k)); - if (!tmp.endsWith('/')) tmp += '/'; - tmp += encodedProgramName; - path[k] = ::strdup(tmp.constData()); - } - } - } - } - - // Start the process manager, and fork off the child process. - processManager()->lock(); -#if defined(Q_OS_QNX) - pid_t childPid = spawnChild(workingDirPtr, argv, envp); -#else - pid_t childPid = fork(); - int lastForkErrno = errno; -#endif - if (childPid != 0) { - // Clean up duplicated memory. - free(dupProgramName); - for (int i = 1; i <= arguments.count(); ++i) - free(argv[i]); - for (int i = 0; i < envc; ++i) - free(envp[i]); - for (int i = 0; i < pathc; ++i) - free(path[i]); - delete [] argv; - delete [] envp; - delete [] path; - } - - // This is not a valid check under QNX, because the semantics are - // different. While under other platforms where fork() may succeed and exec() can still fail, - // causing the childPid to hold a valid value (and thus evaluating the - // following if to false), and then signaling the error via - // childStartedPipe, under QNX on the other hand, spawn() return value will be assigned - // to childPid (which will be -1 in case of failure). This will force - // QProcess to cleanup, instead of signaling the error via - // childStartedPipe. Since it will invalidade the pipes, functions like - // QProcess::waitForStarted() will fail, for childStartedPipe will be - // '-1' and mess with the select() calls. -#if !defined(Q_OS_QNX) - if (childPid < 0) { - // Cleanup, report error and return -#if defined (QPROCESS_DEBUG) - qDebug("fork failed: %s", qPrintable(qt_error_string(lastForkErrno))); -#endif - processManager()->unlock(); - q->setProcessState(QProcess::NotRunning); - processError = QProcess::FailedToStart; - q->setErrorString(QProcess::tr("Resource error (fork failure): %1").arg(qt_error_string(lastForkErrno))); - emit q->error(processError); - cleanup(); - return; - } - - // Start the child. - if (childPid == 0) { - execChild(workingDirPtr, path, argv, envp); - ::_exit(-1); - } -#endif - - // Register the child. In the mean time, we can get a SIGCHLD, so we need - // to keep the lock held to avoid a race to catch the child. - processManager()->add(childPid, q); - pid = Q_PID(childPid); - processManager()->unlock(); - - // parent - // close the ends we don't use and make all pipes non-blocking - ::fcntl(deathPipe[0], F_SETFL, ::fcntl(deathPipe[0], F_GETFL) | O_NONBLOCK); - qt_safe_close(childStartedPipe[1]); - childStartedPipe[1] = -1; - - if (stdinChannel.pipe[0] != -1) { - qt_safe_close(stdinChannel.pipe[0]); - stdinChannel.pipe[0] = -1; - } - - if (stdinChannel.pipe[1] != -1) - ::fcntl(stdinChannel.pipe[1], F_SETFL, ::fcntl(stdinChannel.pipe[1], F_GETFL) | O_NONBLOCK); - - if (stdoutChannel.pipe[1] != -1) { - qt_safe_close(stdoutChannel.pipe[1]); - stdoutChannel.pipe[1] = -1; - } - - if (stdoutChannel.pipe[0] != -1) - ::fcntl(stdoutChannel.pipe[0], F_SETFL, ::fcntl(stdoutChannel.pipe[0], F_GETFL) | O_NONBLOCK); - - if (stderrChannel.pipe[1] != -1) { - qt_safe_close(stderrChannel.pipe[1]); - stderrChannel.pipe[1] = -1; - } - if (stderrChannel.pipe[0] != -1) - ::fcntl(stderrChannel.pipe[0], F_SETFL, ::fcntl(stderrChannel.pipe[0], F_GETFL) | O_NONBLOCK); -#endif /* Q_OS_GENODE */ -} - -#ifndef Q_OS_GENODE -#if defined(Q_OS_QNX) -static pid_t doSpawn(int fd_count, int fd_map[], char **argv, char **envp, - const char *workingDir, bool spawn_detached) -{ - // A multi threaded QNX Process can't fork so we call spawn() instead. - - struct inheritance inherit; - memset(&inherit, 0, sizeof(inherit)); - inherit.flags |= SPAWN_SETSID; - inherit.flags |= SPAWN_CHECK_SCRIPT; - if (spawn_detached) - inherit.flags |= SPAWN_NOZOMBIE; - inherit.flags |= SPAWN_SETSIGDEF; - sigaddset(&inherit.sigdefault, SIGPIPE); // reset the signal that we ignored - - // enter the working directory - const char *oldWorkingDir = 0; - char buff[PATH_MAX + 1]; - - if (workingDir) { - //we need to freeze everyone in order to avoid race conditions with //chdir(). - if (ThreadCtl(_NTO_TCTL_THREADS_HOLD, 0) == -1) - qWarning("ThreadCtl(): cannot hold threads: %s", qPrintable(qt_error_string(errno))); - - oldWorkingDir = QT_GETCWD(buff, PATH_MAX + 1); - if (QT_CHDIR(workingDir) == -1) - qWarning("ThreadCtl(): failed to chdir to %s", workingDir); - } - - pid_t childPid; - EINTR_LOOP(childPid, ::spawn(argv[0], fd_count, fd_map, &inherit, argv, envp)); - if (childPid == -1) { - inherit.flags |= SPAWN_SEARCH_PATH; - EINTR_LOOP(childPid, ::spawn(argv[0], fd_count, fd_map, &inherit, argv, envp)); - } - - if (oldWorkingDir) { - if (QT_CHDIR(oldWorkingDir) == -1) - qWarning("ThreadCtl(): failed to chdir to %s", oldWorkingDir); - - if (ThreadCtl(_NTO_TCTL_THREADS_CONT, 0) == -1) - qFatal("ThreadCtl(): cannot resume threads: %s", qPrintable(qt_error_string(errno))); - } - - return childPid; -} - -pid_t QProcessPrivate::spawnChild(const char *workingDir, char **argv, char **envp) -{ - // we need to manually fill in fd_map - // to inherit the file descriptors from - // the parent - const int fd_count = sysconf(_SC_OPEN_MAX); - QVarLengthArray<int, 1024> fd_map(fd_count); - - for (int i = 3; i < fd_count; ++i) { - // here we rely that fcntl returns -1 and - // sets errno to EBADF - const int flags = ::fcntl(i, F_GETFD); - - fd_map[i] = ((flags >= 0) && !(flags & FD_CLOEXEC)) - ? i : SPAWN_FDCLOSED; - } - - switch (processChannelMode) { - case QProcess::ForwardedChannels: - fd_map[0] = stdinChannel.pipe[0]; - fd_map[1] = QT_FILENO(stdout); - fd_map[2] = QT_FILENO(stderr); - break; - case QProcess::MergedChannels: - fd_map[0] = stdinChannel.pipe[0]; - fd_map[1] = stdoutChannel.pipe[1]; - fd_map[2] = stdoutChannel.pipe[1]; - break; - case QProcess::SeparateChannels: - fd_map[0] = stdinChannel.pipe[0]; - fd_map[1] = stdoutChannel.pipe[1]; - fd_map[2] = stderrChannel.pipe[1]; - break; - } - - pid_t childPid = doSpawn(fd_count, fd_map.data(), argv, envp, workingDir, false); - - if (childPid == -1) { - QString error = qt_error_string(errno); - qt_safe_write(childStartedPipe[1], error.data(), error.length() * sizeof(QChar)); - qt_safe_close(childStartedPipe[1]); - childStartedPipe[1] = -1; - } - - return childPid; -} - -#else - -void QProcessPrivate::execChild(const char *workingDir, char **path, char **argv, char **envp) -{ - ::signal(SIGPIPE, SIG_DFL); // reset the signal that we ignored - - Q_Q(QProcess); - - // copy the stdin socket (without closing on exec) - qt_safe_dup2(stdinChannel.pipe[0], fileno(stdin), 0); - - // copy the stdout and stderr if asked to - if (processChannelMode != QProcess::ForwardedChannels) { - qt_safe_dup2(stdoutChannel.pipe[1], fileno(stdout), 0); - - // merge stdout and stderr if asked to - if (processChannelMode == QProcess::MergedChannels) { - qt_safe_dup2(fileno(stdout), fileno(stderr), 0); - } else { - qt_safe_dup2(stderrChannel.pipe[1], fileno(stderr), 0); - } - } - - // make sure this fd is closed if execvp() succeeds - qt_safe_close(childStartedPipe[0]); - - // enter the working directory - if (workingDir) { - if (QT_CHDIR(workingDir) == -1) - qWarning("QProcessPrivate::execChild() failed to chdir to %s", workingDir); - } - - // this is a virtual call, and it base behavior is to do nothing. - q->setupChildProcess(); - - // execute the process - if (!envp) { - qt_safe_execvp(argv[0], argv); - } else { - if (path) { - char **arg = path; - while (*arg) { - argv[0] = *arg; -#if defined (QPROCESS_DEBUG) - fprintf(stderr, "QProcessPrivate::execChild() searching / starting %s\n", argv[0]); -#endif - qt_safe_execve(argv[0], argv, envp); - ++arg; - } - } else { -#if defined (QPROCESS_DEBUG) - fprintf(stderr, "QProcessPrivate::execChild() starting %s\n", argv[0]); -#endif - qt_safe_execve(argv[0], argv, envp); - } - } - - // notify failure - QString error = qt_error_string(errno); -#if defined (QPROCESS_DEBUG) - fprintf(stderr, "QProcessPrivate::execChild() failed (%s), notifying parent process\n", qPrintable(error)); -#endif - qt_safe_write(childStartedPipe[1], error.data(), error.length() * sizeof(QChar)); - qt_safe_close(childStartedPipe[1]); - childStartedPipe[1] = -1; -} -#endif -#endif /* Q_OS_GENODE */ - -bool QProcessPrivate::processStarted() -{ -#ifdef Q_OS_GENODE -#if defined QPROCESS_DEBUG - qDebug() << "QProcessPrivate::processStarted()"; -#endif - return false; -#else - ushort buf[errorBufferMax]; - int i = qt_safe_read(childStartedPipe[0], &buf, sizeof buf); - if (startupSocketNotifier) { - startupSocketNotifier->setEnabled(false); - startupSocketNotifier->deleteLater(); - startupSocketNotifier = 0; - } - qt_safe_close(childStartedPipe[0]); - childStartedPipe[0] = -1; - -#if defined (QPROCESS_DEBUG) - qDebug("QProcessPrivate::processStarted() == %s", i <= 0 ? "true" : "false"); -#endif - - // did we read an error message? - if (i > 0) - q_func()->setErrorString(QString((const QChar *)buf, i / sizeof(QChar))); - - return i <= 0; -#endif /* Q_OS_GENODE */ -} - -qint64 QProcessPrivate::bytesAvailableFromStdout() const -{ -#ifdef Q_OS_GENODE -#if defined QPROCESS_DEBUG - qDebug() << "QProcessPrivate::bytesAvailableFromStdout()"; -#endif - return 0; -#else - int nbytes = 0; - qint64 available = 0; - if (::ioctl(stdoutChannel.pipe[0], FIONREAD, (char *) &nbytes) >= 0) - available = (qint64) nbytes; -#if defined (QPROCESS_DEBUG) - qDebug("QProcessPrivate::bytesAvailableFromStdout() == %lld", available); -#endif - return available; -#endif /* Q_OS_GENODE */ -} - -qint64 QProcessPrivate::bytesAvailableFromStderr() const -{ -#ifdef Q_OS_GENODE -#if defined QPROCESS_DEBUG - qDebug() << "QProcessPrivate::bytesAvailableFromStderr()"; -#endif - return 0; -#else - int nbytes = 0; - qint64 available = 0; - if (::ioctl(stderrChannel.pipe[0], FIONREAD, (char *) &nbytes) >= 0) - available = (qint64) nbytes; -#if defined (QPROCESS_DEBUG) - qDebug("QProcessPrivate::bytesAvailableFromStderr() == %lld", available); -#endif - return available; -#endif /* Q_OS_GENODE */ -} - -qint64 QProcessPrivate::readFromStdout(char *data, qint64 maxlen) -{ -#ifdef Q_OS_GENODE -#if defined QPROCESS_DEBUG - qDebug() << "QProcessPrivate::readFromStdout()"; -#endif - return 0; -#else - qint64 bytesRead = qt_safe_read(stdoutChannel.pipe[0], data, maxlen); -#if defined QPROCESS_DEBUG - qDebug("QProcessPrivate::readFromStdout(%p \"%s\", %lld) == %lld", - data, qt_prettyDebug(data, bytesRead, 16).constData(), maxlen, bytesRead); -#endif - return bytesRead; -#endif /* Q_OS_GENODE */ -} - -qint64 QProcessPrivate::readFromStderr(char *data, qint64 maxlen) -{ -#ifdef Q_OS_GENODE -#if defined QPROCESS_DEBUG - qDebug() << "QProcessPrivate::readFromStderr()"; -#endif - return 0; -#else - qint64 bytesRead = qt_safe_read(stderrChannel.pipe[0], data, maxlen); -#if defined QPROCESS_DEBUG - qDebug("QProcessPrivate::readFromStderr(%p \"%s\", %lld) == %lld", - data, qt_prettyDebug(data, bytesRead, 16).constData(), maxlen, bytesRead); -#endif - return bytesRead; -#endif /* Q_OS_GENODE */ -} - -qint64 QProcessPrivate::writeToStdin(const char *data, qint64 maxlen) -{ -#ifdef Q_OS_GENODE -#if defined QPROCESS_DEBUG - qDebug() << "writeToStdin()"; -#endif - return 0; -#else - qint64 written = qt_safe_write_nosignal(stdinChannel.pipe[1], data, maxlen); -#if defined QPROCESS_DEBUG - qDebug("QProcessPrivate::writeToStdin(%p \"%s\", %lld) == %lld", - data, qt_prettyDebug(data, maxlen, 16).constData(), maxlen, written); - if (written == -1) - qDebug("QProcessPrivate::writeToStdin(), failed to write (%s)", qPrintable(qt_error_string(errno))); -#endif - // If the O_NONBLOCK flag is set and If some data can be written without blocking - // the process, write() will transfer what it can and return the number of bytes written. - // Otherwise, it will return -1 and set errno to EAGAIN - if (written == -1 && errno == EAGAIN) - written = 0; - return written; -#endif /* Q_OS_GENODE */ -} - -void QProcessPrivate::terminateProcess() -{ -#if defined (QPROCESS_DEBUG) - qDebug("QProcessPrivate::terminateProcess()"); -#endif -#ifndef Q_OS_GENODE - if (pid) - ::kill(pid_t(pid), SIGTERM); -#endif /* Q_OS_GENODE */ -} - -void QProcessPrivate::killProcess() -{ -#if defined (QPROCESS_DEBUG) - qDebug("QProcessPrivate::killProcess()"); -#endif - -#ifdef Q_OS_GENODE - if (launchpad_child) { - launchpad()->exit_child(launchpad_child); - } -#else - if (pid) - ::kill(pid_t(pid), SIGKILL); -#endif /* Q_OS_GENODE */ -} - -#ifndef Q_OS_GENODE -static int select_msecs(int nfds, fd_set *fdread, fd_set *fdwrite, int timeout) -{ - if (timeout < 0) - return qt_safe_select(nfds, fdread, fdwrite, 0, 0); - - struct timeval tv; - tv.tv_sec = timeout / 1000; - tv.tv_usec = (timeout % 1000) * 1000; - return qt_safe_select(nfds, fdread, fdwrite, 0, &tv); -} - -/* - Returns the difference between msecs and elapsed. If msecs is -1, - however, -1 is returned. -*/ -static int qt_timeout_value(int msecs, int elapsed) -{ - if (msecs == -1) - return -1; - - int timeout = msecs - elapsed; - return timeout < 0 ? 0 : timeout; -} -#endif /* Q_OS_GENODE */ - -bool QProcessPrivate::waitForStarted(int msecs) -{ - Q_Q(QProcess); - -#if defined (QPROCESS_DEBUG) - qDebug("QProcessPrivate::waitForStarted(%d) waiting for child to start (fd = %d)", msecs, - childStartedPipe[0]); -#endif - -#ifdef Q_OS_GENODE - return false; -#else - fd_set fds; - FD_ZERO(&fds); - FD_SET(childStartedPipe[0], &fds); - if (select_msecs(childStartedPipe[0] + 1, &fds, 0, msecs) == 0) { - processError = QProcess::Timedout; - q->setErrorString(QProcess::tr("Process operation timed out")); -#if defined (QPROCESS_DEBUG) - qDebug("QProcessPrivate::waitForStarted(%d) == false (timed out)", msecs); -#endif - return false; - } - - bool startedEmitted = _q_startupNotification(); -#if defined (QPROCESS_DEBUG) - qDebug("QProcessPrivate::waitForStarted() == %s", startedEmitted ? "true" : "false"); -#endif - return startedEmitted; -#endif /* Q_OS_GENODE */ -} - -bool QProcessPrivate::waitForReadyRead(int msecs) -{ - Q_Q(QProcess); -#if defined (QPROCESS_DEBUG) - qDebug("QProcessPrivate::waitForReadyRead(%d)", msecs); -#endif - -#ifdef Q_OS_GENODE - return false; -#else - QElapsedTimer stopWatch; - stopWatch.start(); - - forever { - fd_set fdread; - fd_set fdwrite; - - FD_ZERO(&fdread); - FD_ZERO(&fdwrite); - - int nfds = deathPipe[0]; - FD_SET(deathPipe[0], &fdread); - - if (processState == QProcess::Starting) - add_fd(nfds, childStartedPipe[0], &fdread); - - if (stdoutChannel.pipe[0] != -1) - add_fd(nfds, stdoutChannel.pipe[0], &fdread); - if (stderrChannel.pipe[0] != -1) - add_fd(nfds, stderrChannel.pipe[0], &fdread); - - if (!writeBuffer.isEmpty() && stdinChannel.pipe[1] != -1) - add_fd(nfds, stdinChannel.pipe[1], &fdwrite); - - int timeout = qt_timeout_value(msecs, stopWatch.elapsed()); - int ret = select_msecs(nfds + 1, &fdread, &fdwrite, timeout); - if (ret < 0) { - break; - } - if (ret == 0) { - processError = QProcess::Timedout; - q->setErrorString(QProcess::tr("Process operation timed out")); - return false; - } - - if (childStartedPipe[0] != -1 && FD_ISSET(childStartedPipe[0], &fdread)) { - if (!_q_startupNotification()) - return false; - } - - bool readyReadEmitted = false; - if (stdoutChannel.pipe[0] != -1 && FD_ISSET(stdoutChannel.pipe[0], &fdread)) { - bool canRead = _q_canReadStandardOutput(); - if (processChannel == QProcess::StandardOutput && canRead) - readyReadEmitted = true; - } - if (stderrChannel.pipe[0] != -1 && FD_ISSET(stderrChannel.pipe[0], &fdread)) { - bool canRead = _q_canReadStandardError(); - if (processChannel == QProcess::StandardError && canRead) - readyReadEmitted = true; - } - if (readyReadEmitted) - return true; - - if (stdinChannel.pipe[1] != -1 && FD_ISSET(stdinChannel.pipe[1], &fdwrite)) - _q_canWrite(); - - if (deathPipe[0] == -1 || FD_ISSET(deathPipe[0], &fdread)) { - if (_q_processDied()) - return false; - } - } - return false; -#endif /* Q_OS_GENODE */ -} - -bool QProcessPrivate::waitForBytesWritten(int msecs) -{ - Q_Q(QProcess); -#if defined (QPROCESS_DEBUG) - qDebug("QProcessPrivate::waitForBytesWritten(%d)", msecs); -#endif - -#ifdef Q_OS_GENODE - return false; -#else - QElapsedTimer stopWatch; - stopWatch.start(); - - while (!writeBuffer.isEmpty()) { - fd_set fdread; - fd_set fdwrite; - - FD_ZERO(&fdread); - FD_ZERO(&fdwrite); - - int nfds = deathPipe[0]; - FD_SET(deathPipe[0], &fdread); - - if (processState == QProcess::Starting) - add_fd(nfds, childStartedPipe[0], &fdread); - - if (stdoutChannel.pipe[0] != -1) - add_fd(nfds, stdoutChannel.pipe[0], &fdread); - if (stderrChannel.pipe[0] != -1) - add_fd(nfds, stderrChannel.pipe[0], &fdread); - - - if (!writeBuffer.isEmpty() && stdinChannel.pipe[1] != -1) - add_fd(nfds, stdinChannel.pipe[1], &fdwrite); - - int timeout = qt_timeout_value(msecs, stopWatch.elapsed()); - int ret = select_msecs(nfds + 1, &fdread, &fdwrite, timeout); - if (ret < 0) { - break; - } - - if (ret == 0) { - processError = QProcess::Timedout; - q->setErrorString(QProcess::tr("Process operation timed out")); - return false; - } - - if (childStartedPipe[0] != -1 && FD_ISSET(childStartedPipe[0], &fdread)) { - if (!_q_startupNotification()) - return false; - } - - if (stdinChannel.pipe[1] != -1 && FD_ISSET(stdinChannel.pipe[1], &fdwrite)) - return _q_canWrite(); - - if (stdoutChannel.pipe[0] != -1 && FD_ISSET(stdoutChannel.pipe[0], &fdread)) - _q_canReadStandardOutput(); - - if (stderrChannel.pipe[0] != -1 && FD_ISSET(stderrChannel.pipe[0], &fdread)) - _q_canReadStandardError(); - - if (deathPipe[0] == -1 || FD_ISSET(deathPipe[0], &fdread)) { - if (_q_processDied()) - return false; - } - } - - return false; -#endif /* Q_OS_GENODE */ -} - -bool QProcessPrivate::waitForFinished(int msecs) -{ - Q_Q(QProcess); -#if defined (QPROCESS_DEBUG) - qDebug("QProcessPrivate::waitForFinished(%d)", msecs); -#endif - -#ifdef Q_OS_GENODE - return false; -#else - QElapsedTimer stopWatch; - stopWatch.start(); - - forever { - fd_set fdread; - fd_set fdwrite; - int nfds = -1; - - FD_ZERO(&fdread); - FD_ZERO(&fdwrite); - - if (processState == QProcess::Starting) - add_fd(nfds, childStartedPipe[0], &fdread); - - if (stdoutChannel.pipe[0] != -1) - add_fd(nfds, stdoutChannel.pipe[0], &fdread); - if (stderrChannel.pipe[0] != -1) - add_fd(nfds, stderrChannel.pipe[0], &fdread); - - if (processState == QProcess::Running) - add_fd(nfds, deathPipe[0], &fdread); - - if (!writeBuffer.isEmpty() && stdinChannel.pipe[1] != -1) - add_fd(nfds, stdinChannel.pipe[1], &fdwrite); - - int timeout = qt_timeout_value(msecs, stopWatch.elapsed()); - int ret = select_msecs(nfds + 1, &fdread, &fdwrite, timeout); - if (ret < 0) { - break; - } - if (ret == 0) { - processError = QProcess::Timedout; - q->setErrorString(QProcess::tr("Process operation timed out")); - return false; - } - - if (childStartedPipe[0] != -1 && FD_ISSET(childStartedPipe[0], &fdread)) { - if (!_q_startupNotification()) - return false; - } - if (stdinChannel.pipe[1] != -1 && FD_ISSET(stdinChannel.pipe[1], &fdwrite)) - _q_canWrite(); - - if (stdoutChannel.pipe[0] != -1 && FD_ISSET(stdoutChannel.pipe[0], &fdread)) - _q_canReadStandardOutput(); - - if (stderrChannel.pipe[0] != -1 && FD_ISSET(stderrChannel.pipe[0], &fdread)) - _q_canReadStandardError(); - - if (deathPipe[0] == -1 || FD_ISSET(deathPipe[0], &fdread)) { - if (_q_processDied()) - return true; - } - } - return false; -#endif /* Q_OS_GENODE */ -} - -#ifndef Q_OS_GENODE -bool QProcessPrivate::waitForWrite(int msecs) -{ - fd_set fdwrite; - FD_ZERO(&fdwrite); - FD_SET(stdinChannel.pipe[1], &fdwrite); - return select_msecs(stdinChannel.pipe[1] + 1, 0, &fdwrite, msecs < 0 ? 0 : msecs) == 1; -} -#endif /* Q_OS_GENODE */ - -void QProcessPrivate::findExitCode() -{ -#ifdef Q_OS_GENODE -#ifdef QPROCESS_DEBUG - qDebug() << "QProcessPrivate::findExitCode()"; -#endif -#else - Q_Q(QProcess); - processManager()->remove(q); -#endif -} - -bool QProcessPrivate::waitForDeadChild() -{ -#ifdef Q_OS_GENODE -#ifdef QPROCESS_DEBUG - qDebug() << QProcessPrivate::waitForDeadChild(); -#endif - - return false; -#else - Q_Q(QProcess); - - // read a byte from the death pipe - char c; - qt_safe_read(deathPipe[0], &c, 1); - - // check if our process is dead - int exitStatus; - if (qt_safe_waitpid(pid_t(pid), &exitStatus, WNOHANG) > 0) { - processManager()->remove(q); - crashed = !WIFEXITED(exitStatus); - exitCode = WEXITSTATUS(exitStatus); -#if defined QPROCESS_DEBUG - qDebug() << "QProcessPrivate::waitForDeadChild() dead with exitCode" - << exitCode << ", crashed?" << crashed; -#endif - return true; - } -#if defined QPROCESS_DEBUG - qDebug() << "QProcessPrivate::waitForDeadChild() not dead!"; -#endif - return false; -#endif /* Q_OS_GENODE */ -} - -void QProcessPrivate::_q_notified() -{ -} - -#if defined(Q_OS_QNX) -bool QProcessPrivate::startDetached(const QString &program, const QStringList &arguments, const QString &workingDirectory, qint64 *pid) -{ - const int fd_count = 3; - int fd_map[fd_count] = { QT_FILENO(stdin), QT_FILENO(stdout), QT_FILENO(stderr) }; - - QList<QByteArray> enc_args; - enc_args.append(QFile::encodeName(program)); - for (int i = 0; i < arguments.size(); ++i) - enc_args.append(arguments.at(i).toLocal8Bit()); - - const int argc = enc_args.size(); - QScopedArrayPointer<char*> raw_argv(new char*[argc + 1]); - for (int i = 0; i < argc; ++i) - raw_argv[i] = const_cast<char *>(enc_args.at(i).data()); - raw_argv[argc] = 0; - - char **envp = 0; // inherit environment - - // Encode the working directory if it's non-empty, otherwise just pass 0. - const char *workingDirPtr = 0; - QByteArray encodedWorkingDirectory; - if (!workingDirectory.isEmpty()) { - encodedWorkingDirectory = QFile::encodeName(workingDirectory); - workingDirPtr = encodedWorkingDirectory.constData(); - } - - pid_t childPid = doSpawn(fd_count, fd_map, raw_argv.data(), envp, workingDirPtr, true); - if (pid && childPid != -1) - *pid = childPid; - - return childPid != -1; -} - -#else - -bool QProcessPrivate::startDetached(const QString &program, const QStringList &arguments, const QString &workingDirectory, qint64 *pid) -{ -#ifdef Q_OS_GENODE -#ifdef QPROCESS_DEBUG - qDebug() << "QProcessPrivate::startDetached()"; -#endif - - return false; -#else - processManager()->start(); - - QByteArray encodedWorkingDirectory = QFile::encodeName(workingDirectory); - - // To catch the startup of the child - int startedPipe[2]; - qt_safe_pipe(startedPipe); - // To communicate the pid of the child - int pidPipe[2]; - qt_safe_pipe(pidPipe); - - pid_t childPid = fork(); - if (childPid == 0) { - struct sigaction noaction; - memset(&noaction, 0, sizeof(noaction)); - noaction.sa_handler = SIG_IGN; - ::sigaction(SIGPIPE, &noaction, 0); - - ::setsid(); - - qt_safe_close(startedPipe[0]); - qt_safe_close(pidPipe[0]); - - pid_t doubleForkPid = fork(); - if (doubleForkPid == 0) { - qt_safe_close(pidPipe[1]); - - if (!encodedWorkingDirectory.isEmpty()) { - if (QT_CHDIR(encodedWorkingDirectory.constData()) == -1) - qWarning("QProcessPrivate::startDetached: failed to chdir to %s", encodedWorkingDirectory.constData()); - } - - char **argv = new char *[arguments.size() + 2]; - for (int i = 0; i < arguments.size(); ++i) - argv[i + 1] = ::strdup(QFile::encodeName(arguments.at(i)).constData()); - argv[arguments.size() + 1] = 0; - - if (!program.contains(QLatin1Char('/'))) { - const QString path = QString::fromLocal8Bit(::getenv("PATH")); - if (!path.isEmpty()) { - QStringList pathEntries = path.split(QLatin1Char(':')); - for (int k = 0; k < pathEntries.size(); ++k) { - QByteArray tmp = QFile::encodeName(pathEntries.at(k)); - if (!tmp.endsWith('/')) tmp += '/'; - tmp += QFile::encodeName(program); - argv[0] = tmp.data(); - qt_safe_execv(argv[0], argv); - } - } - } else { - QByteArray tmp = QFile::encodeName(program); - argv[0] = tmp.data(); - qt_safe_execv(argv[0], argv); - } - - struct sigaction noaction; - memset(&noaction, 0, sizeof(noaction)); - noaction.sa_handler = SIG_IGN; - ::sigaction(SIGPIPE, &noaction, 0); - - // '\1' means execv failed - char c = '\1'; - qt_safe_write(startedPipe[1], &c, 1); - qt_safe_close(startedPipe[1]); - ::_exit(1); - } else if (doubleForkPid == -1) { - struct sigaction noaction; - memset(&noaction, 0, sizeof(noaction)); - noaction.sa_handler = SIG_IGN; - ::sigaction(SIGPIPE, &noaction, 0); - - // '\2' means internal error - char c = '\2'; - qt_safe_write(startedPipe[1], &c, 1); - } - - qt_safe_close(startedPipe[1]); - qt_safe_write(pidPipe[1], (const char *)&doubleForkPid, sizeof(pid_t)); - if (QT_CHDIR("/") == -1) - qWarning("QProcessPrivate::startDetached: failed to chdir to /"); - ::_exit(1); - } - - qt_safe_close(startedPipe[1]); - qt_safe_close(pidPipe[1]); - - if (childPid == -1) { - qt_safe_close(startedPipe[0]); - qt_safe_close(pidPipe[0]); - return false; - } - - char reply = '\0'; - int startResult = qt_safe_read(startedPipe[0], &reply, 1); - int result; - qt_safe_close(startedPipe[0]); - qt_safe_waitpid(childPid, &result, 0); - bool success = (startResult != -1 && reply == '\0'); - if (success && pid) { - pid_t actualPid = 0; - if (qt_safe_read(pidPipe[0], (char *)&actualPid, sizeof(pid_t)) == sizeof(pid_t)) { - *pid = actualPid; - } else { - *pid = 0; - } - } - qt_safe_close(pidPipe[0]); - return success; -#endif /* Q_OS_GENODE */ -} -#endif - -void QProcessPrivate::initializeProcessManager() -{ -#ifdef Q_OS_GENODE -#ifdef QPROCESS_DEBUG - qDebug() << "QProcessPrivate::initializeProcessManager()"; -#endif -#else - (void) processManager(); -#endif /* Q_OS_GENODE */ -} - -QT_END_NAMESPACE - -#ifndef Q_OS_GENODE -#include "qprocess_unix.moc" -#endif /* Q_OS_GENODE */ - -#endif // QT_NO_PROCESS diff --git a/repos/ports/ports/arora.hash b/repos/ports/ports/arora.hash index 92272673ed..34ce940c05 100644 --- a/repos/ports/ports/arora.hash +++ b/repos/ports/ports/arora.hash @@ -1 +1 @@ -031d110045f9db5f0bf9970c503b680f30fff6c5 +8537dffb154dacd9efbcfdd99464866a8e4ef0ef diff --git a/repos/ports/src/app/arora/patches/arora_disable_qprocess.patch b/repos/ports/src/app/arora/patches/arora_disable_qprocess.patch new file mode 100644 index 0000000000..8b38d0e9c9 --- /dev/null +++ b/repos/ports/src/app/arora/patches/arora_disable_qprocess.patch @@ -0,0 +1,53 @@ +arora_disable_qprocess.patch + +From: Christian Prochaska <christian.prochaska@genode-labs.com> + + +--- + src/bookmarks/bookmarksmanager.cpp | 3 +++ + src/downloadmanager.cpp | 4 ++++ + 2 files changed, 7 insertions(+) + +diff --git a/src/bookmarks/bookmarksmanager.cpp b/src/bookmarks/bookmarksmanager.cpp +index d3a21e2..3ddaa4a 100644 +--- a/src/bookmarks/bookmarksmanager.cpp ++++ b/src/bookmarks/bookmarksmanager.cpp +@@ -286,6 +286,8 @@ BookmarksModel *BookmarksManager::bookmarksModel() + + void BookmarksManager::importBookmarks() + { ++ /* QProcess is not available on Genode */ ++#if 0 + QStringList supportedFormats; + supportedFormats << tr("XBEL bookmarks").append(QLatin1String("(*.xbel *.xml)")); + supportedFormats << tr("HTML Netscape bookmarks").append(QLatin1String("(*.html)")); +@@ -330,6 +332,7 @@ void BookmarksManager::importBookmarks() + importRootNode->setType(BookmarkNode::Folder); + importRootNode->title = (tr("Imported %1").arg(QDate::currentDate().toString(Qt::SystemLocaleShortDate))); + addBookmark(menu(), importRootNode); ++#endif + } + + void BookmarksManager::exportBookmarks() +diff --git a/src/downloadmanager.cpp b/src/downloadmanager.cpp +index b0da144..e7b6000 100644 +--- a/src/downloadmanager.cpp ++++ b/src/downloadmanager.cpp +@@ -525,6 +525,9 @@ bool DownloadManager::allowQuit() + + bool DownloadManager::externalDownload(const QUrl &url) + { ++ /* QProcess is not available on Genode */ ++ return false; ++#if 0 + QSettings settings; + settings.beginGroup(QLatin1String("downloadmanager")); + if (!settings.value(QLatin1String("external"), false).toBool()) +@@ -543,6 +546,7 @@ bool DownloadManager::externalDownload(const QUrl &url) + return false; + + return QProcess::startDetached(args.takeFirst(), args << QString::fromUtf8(url.toEncoded())); ++#endif + } + + void DownloadManager::download(const QNetworkRequest &request, bool requestFileName) diff --git a/repos/ports/src/app/arora/patches/series b/repos/ports/src/app/arora/patches/series index 9fd01a50e7..46c0217a85 100644 --- a/repos/ports/src/app/arora/patches/series +++ b/repos/ports/src/app/arora/patches/series @@ -6,3 +6,4 @@ arora_disable_adblock.patch arora_bookmarks.patch arora_startpage.patch arora_disable_ssl_messageboxes.patch +arora_disable_qprocess.patch