⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 qprocess_unix.cpp

📁 QT 开发环境里面一个很重要的文件
💻 CPP
📖 第 1 页 / 共 3 页
字号:
            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] = open(fname, O_RDONLY)) != -1)                return true;    // success            q->setErrorString(QLatin1String(QT_TRANSLATE_NOOP(QProcess, "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] = open(fname, mode, 0666)) != -1)                return true; // success            q->setErrorString(QLatin1String(QT_TRANSLATE_NOOP(QProcess, "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;        }    }}void QProcessPrivate::startProcess(){    Q_Q(QProcess);#if defined (QPROCESS_DEBUG)    qDebug("QProcessPrivate::startProcess()");#endif    processManager()->start();    // Initialize pipes    qt_create_pipe(childStartedPipe);    if (threadData->eventDispatcher) {        startupSocketNotifier = new QSocketNotifier(childStartedPipe[0],                                                    QSocketNotifier::Read, q);        QObject::connect(startupSocketNotifier, SIGNAL(activated(int)),                         q, SLOT(_q_startupNotification()));    }    qt_create_pipe(deathPipe);    ::fcntl(deathPipe[0], F_SETFD, FD_CLOEXEC);    ::fcntl(deathPipe[1], F_SETFD, FD_CLOEXEC);    if (threadData->eventDispatcher) {        deathNotifier = new QSocketNotifier(deathPipe[0],                                            QSocketNotifier::Read, q);        QObject::connect(deathNotifier, SIGNAL(activated(int)),                         q, SLOT(_q_processDied()));    }    if (!createChannel(stdinChannel) ||        !createChannel(stdoutChannel) ||        !createChannel(stderrChannel))        return;    // Start the process (platform dependent)    processState = QProcess::Starting;    emit q->stateChanged(processState);    QByteArray encodedProg = QFile::encodeName(program);    processManager()->lock();    pid_t childPid = fork();    if (childPid < 0) {        // Cleanup, report error and return        processManager()->unlock();        processState = QProcess::NotRunning;        emit q->stateChanged(processState);        processError = QProcess::FailedToStart;        q->setErrorString(QLatin1String(QT_TRANSLATE_NOOP(QProcess, "Resource error (fork failure)")));        emit q->error(processError);        cleanup();        return;    }    if (childPid == 0) {        execChild(encodedProg);        ::_exit(-1);    }    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_native_close(childStartedPipe[1]);    childStartedPipe[1] = -1;    if (stdinChannel.pipe[0] != -1) {        qt_native_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_native_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_native_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);}void QProcessPrivate::execChild(const QByteArray &programName){    ::signal(SIGPIPE, SIG_DFL);         // reset the signal that we ignored    QByteArray encodedProgramName = programName;    Q_Q(QProcess);    // 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;    // allow invoking of .app bundles on the Mac.#ifdef Q_OS_MAC    QFileInfo fileInfo(encodedProgramName);    if (encodedProgramName.endsWith(".app") && fileInfo.isDir()) {        QCFType<CFURLRef> url = CFURLCreateWithFileSystemPath(0,                                                          QCFString(fileInfo.absoluteFilePath()),                                                          kCFURLPOSIXPathStyle, true);        QCFType<CFBundleRef> bundle = CFBundleCreate(0, url);        url = CFBundleCopyExecutableURL(bundle);        if (url) {            QCFString str = CFURLCopyFileSystemPath(url, kCFURLPOSIXPathStyle);            encodedProgramName += "/Contents/MacOS/" + static_cast<QString>(str).toUtf8();        }    }#endif    // add the program name    argv[0] = ::strdup(encodedProgramName.constData());    // add every argument to the list    for (int i = 0; i < arguments.count(); ++i) {        QString arg = arguments.at(i);#ifdef Q_OS_MAC        argv[i + 1] = ::strdup(arg.toUtf8().constData());#else        argv[i + 1] = ::strdup(arg.toLocal8Bit().constData());#endif    }    // copy the stdin socket    qt_native_dup2(stdinChannel.pipe[0], fileno(stdin));    // copy the stdout and stderr if asked to    if (processChannelMode != QProcess::ForwardedChannels) {        qt_native_dup2(stdoutChannel.pipe[1], fileno(stdout));        // merge stdout and stderr if asked to        if (processChannelMode == QProcess::MergedChannels) {            qt_native_dup2(fileno(stdout), fileno(stderr));        } else {            qt_native_dup2(stderrChannel.pipe[1], fileno(stderr));        }    }    // make sure this fd is closed if execvp() succeeds    qt_native_close(childStartedPipe[0]);    ::fcntl(childStartedPipe[1], F_SETFD, FD_CLOEXEC);    // enter the working directory    if (!workingDirectory.isEmpty())        qt_native_chdir(QFile::encodeName(workingDirectory).constData());    // this is a virtual call, and it base behavior is to do nothing.    q->setupChildProcess();    // execute the process    if (environment.isEmpty()) {        qt_native_execvp(argv[0], argv);    } else {        // 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 QString libraryPathString = QLatin1String(libraryPath);        QStringList matches = environment.filter(                QRegExp(QLatin1Char('^') + libraryPathString + QLatin1Char('=')));        const QString envLibraryPath = QString::fromLocal8Bit(::getenv(libraryPath));        if (matches.isEmpty() && !envLibraryPath.isEmpty()) {            QString entry = libraryPathString;            entry += QLatin1Char('=');            entry += envLibraryPath;            environment << libraryPathString + QLatin1Char('=') + envLibraryPath;        }        char **envp = new char *[environment.count() + 1];        envp[environment.count()] = 0;        for (int j = 0; j < environment.count(); ++j) {            QString item = environment.at(j);            envp[j] = ::strdup(item.toLocal8Bit().constData());        }        if (!encodedProgramName.contains("/")) {            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 += encodedProgramName;                    argv[0] = tmp.data();#if defined (QPROCESS_DEBUG)                    fprintf(stderr, "QProcessPrivate::execChild() searching / starting %s\n", argv[0]);#endif                    qt_native_execve(argv[0], argv, envp);                }            }        } else {#if defined (QPROCESS_DEBUG)            fprintf(stderr, "QProcessPrivate::execChild() starting %s\n", argv[0]);#endif            qt_native_execve(argv[0], argv, envp);        }    }    // notify failure#if defined (QPROCESS_DEBUG)    fprintf(stderr, "QProcessPrivate::execChild() failed, notifying parent process\n");#endif    qt_native_write(childStartedPipe[1], "", 1);    qt_native_close(childStartedPipe[1]);    childStartedPipe[1] = -1;}bool QProcessPrivate::processStarted(){    char c;    int i = qt_native_read(childStartedPipe[0], &c, 1);    if (startupSocketNotifier) {        startupSocketNotifier->setEnabled(false);        delete startupSocketNotifier;        startupSocketNotifier = 0;    }    qt_native_close(childStartedPipe[0]);    childStartedPipe[0] = -1;#if defined (QPROCESS_DEBUG)    qDebug("QProcessPrivate::processStarted() == %s", i <= 0 ? "true" : "false");#endif    return i <= 0;}qint64 QProcessPrivate::bytesAvailableFromStdout() const{    size_t nbytes = 0;    qint64 available = 0;    if (::ioctl(stdoutChannel.pipe[0], FIONREAD, (char *) &nbytes) >= 0)        available = (qint64) *((int *) &nbytes);#if defined (QPROCESS_DEBUG)    qDebug("QProcessPrivate::bytesAvailableFromStdout() == %lld", available);#endif    return available;}qint64 QProcessPrivate::bytesAvailableFromStderr() const{    size_t nbytes = 0;    qint64 available = 0;    if (::ioctl(stderrChannel.pipe[0], FIONREAD, (char *) &nbytes) >= 0)        available = (qint64) *((int *) &nbytes);#if defined (QPROCESS_DEBUG)    qDebug("QProcessPrivate::bytesAvailableFromStderr() == %lld", available);#endif    return available;}qint64 QProcessPrivate::readFromStdout(char *data, qint64 maxlen){    qint64 bytesRead = qt_native_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;}qint64 QProcessPrivate::readFromStderr(char *data, qint64 maxlen){    qint64 bytesRead = qt_native_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;}static void qt_ignore_sigpipe(){    // Set to ignore SIGPIPE once only.    static QBasicAtomic atom = Q_ATOMIC_INIT(0);    if (atom.testAndSet(0, 1)) {        struct sigaction noaction;        memset(&noaction, 0, sizeof(noaction));        noaction.sa_handler = SIG_IGN;        qt_native_sigaction(SIGPIPE, &noaction, 0);    }}qint64 QProcessPrivate::writeToStdin(const char *data, qint64 maxlen){    qt_ignore_sigpipe();    qint64 written = qt_native_write(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);#endif    return written;}void QProcessPrivate::terminateProcess(){#if defined (QPROCESS_DEBUG)    qDebug("QProcessPrivate::killProcess()");#endif    if (pid)        ::kill(pid_t(pid), SIGTERM);}void QProcessPrivate::killProcess(){#if defined (QPROCESS_DEBUG)    qDebug("QProcessPrivate::killProcess()");#endif    if (pid)        ::kill(pid_t(pid), SIGKILL);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -