Changeset 181 for trunk/src


Ignore:
Timestamp:
Sep 15, 2009, 11:09:52 AM (16 years ago)
Author:
Dmitry A. Kuminov
Message:

corelib: Fixed stdio redirection in QProcess but it will only work for kLIBC-based child processes for now. See #69.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/corelib/io/qprocess_os2.cpp

    r73 r181  
    104104#include <errno.h>
    105105#include <sys/filio.h>
     106
    106107
    107108QT_BEGIN_NAMESPACE
     
    113114    if (pipe[1] != -1)
    114115        ::close(pipe[1]);
    115     if (::pipe(pipe) != 0) {
    116         qWarning("QProcessPrivate::createPipe: Cannot create pipe %p: %s",
    117                  pipe, qPrintable(qt_error_string(errno)));
     116    // Note: with kLIBC 0.6.3 and earlier (GCC 3.3.5 CSD3), fds created with
     117    // pipe() cannot be used in select(), so use socketpair() instead
     118    if (::socketpair(AF_OS2, SOCK_STREAM, 0, pipe) != 0) {
     119        qWarning("QProcessPrivate::createPipe: ::socketpair() failed with '%s'",
     120                 qPrintable(qt_error_string(errno)));
    118121    }
    119122    ::fcntl(pipe[0], F_SETFD, FD_CLOEXEC);
     
    247250                           const QStringList *environment, bool detached = false)
    248251{
     252
    249253    int mode = detached ? P_DETACH : P_NOWAIT;
    250254
     
    310314
    311315    // start the program
    312     int pid = spawnvpe(mode | P_DEFAULT, encodedProgramName, argv, envv);
     316#ifdef QPROCESS_DEBUG
     317    qDebug("Trying spawnvpe(%d, \"%s\")",
     318           mode, encodedProgramName.constData());
     319#endif
     320    int pid = spawnvpe(mode, encodedProgramName, argv, envv);
    313321
    314322    // if spawnvpe() couldn't find the executable, try .CMD and .BAT
    315323    // extensions (in order of CMD.EXE precedence); spawnvpe() knows how to
    316324    // locate and run them (i.e. using CMD.EXE /c)
    317     if ( pid == -1 && errno == ENOENT ) {
     325    if () {
    318326        encodedProgramName += ".cmd";
    319327        argv[0] = encodedProgramName.data();
    320         pid = spawnvpe(P_NOWAIT | P_DEFAULT, encodedProgramName, argv, envv);
     328#ifdef QPROCESS_DEBUG
     329            qDebug("Trying spawnvpe(%d, \"%s\")",
     330                   mode, encodedProgramName.constData());
     331#endif
     332        pid = spawnvpe(mode, encodedProgramName, argv, envv);
    321333        if ( pid == -1 && errno == ENOENT ) {
    322334            qstrcpy(encodedProgramName.data() + encodedProgramName.length() - 4, ".bat");
    323335            argv[0] = encodedProgramName.data();
    324             pid = spawnvpe(P_NOWAIT | P_DEFAULT, encodedProgramName, argv, envv);
     336#ifdef QPROCESS_DEBUG
     337            qDebug("Trying spawnvpe(%d, \"%s\")",
     338                   mode, encodedProgramName.constData());
     339#endif
     340            pid = spawnvpe(mode, encodedProgramName, argv, envv);
    325341        }
    326342    }
     
    374390            ::dup2(fileno(stdout), fileno(stderr));
    375391        } else {
     392
     393
    376394            ::dup2(stderrChannel.pipe[1], fileno(stderr));
     395
    377396        }
    378397    }
     
    398417        // Cleanup, report error and return
    399418#if defined (QPROCESS_DEBUG)
    400         qDebug("spawnvpe failed: %s", qt_error_string(errno));
     419        qDebug("spawnvpe failed: %s", q));
    401420#endif
    402421        q->setProcessState(QProcess::NotRunning);
    403422        processError = QProcess::FailedToStart;
    404         q->setErrorString(QProcess::tr("Process failed to start: %1").arg(qt_error_string(errno)));
     423        q->setErrorString(QProcess::tr("Process failed to start: %1")
     424                                       .arg(qPrintable(qt_error_string(errno))));
    405425        emit q->error(processError);
    406426        cleanup();
     
    555575}
    556576
    557 static int qt_select(fd_set *fdread, fd_set *fdwrite, int timeout)
     577static int qt_select(fd_set *fdread, fd_set *fdwrite, int timeout)
    558578{
    559579    struct timeval tv;
     
    561581    tv.tv_usec = (timeout % 1000) * 1000;
    562582
    563     int ret = select(FD_SETSIZE, fdread, fdwrite, 0, timeout < 0 ? 0 : &tv);
     583    int ret = select(, fdread, fdwrite, 0, timeout < 0 ? 0 : &tv);
    564584    return ret;
    565585}
     
    597617        FD_ZERO(&fdwrite);
    598618
    599         if (stdoutChannel.pipe[0] != -1)
     619        int maxFd = 0;
     620        if (stdoutChannel.pipe[0] != -1) {
    600621            FD_SET(stdoutChannel.pipe[0], &fdread);
    601         if (stderrChannel.pipe[0] != -1)
     622            maxFd = qMax(maxFd, stdoutChannel.pipe[0]);
     623        }
     624        if (stderrChannel.pipe[0] != -1) {
    602625            FD_SET(stderrChannel.pipe[0], &fdread);
    603 
    604         if (!writeBuffer.isEmpty() && stdinChannel.pipe[1] != -1)
     626            maxFd = qMax(maxFd, stderrChannel.pipe[0]);
     627        }
     628
     629        if (!writeBuffer.isEmpty() && stdinChannel.pipe[1] != -1) {
    605630            FD_SET(stdinChannel.pipe[1], &fdwrite);
     631
     632
    606633
    607634        int timeout = qt_timeout_value(msecs, stopWatch.elapsed());
    608         int ret = qt_select(&fdread, &fdwrite, timeout);
     635        int ret;
     636        if (maxFd >= 0) {
     637            ret = qt_select(maxFd + 1, &fdread, &fdwrite, timeout);
     638        } else {
     639            int exitStatus;
     640            ret = waitpid(pid, &exitStatus, 0);
     641        }
    609642        if (ret < 0) {
    610643            break;
     
    658691        FD_ZERO(&fdwrite);
    659692
    660         if (stdoutChannel.pipe[0] != -1)
     693        int maxFd = 0;
     694        if (stdoutChannel.pipe[0] != -1) {
    661695            FD_SET(stdoutChannel.pipe[0], &fdread);
    662         if (stderrChannel.pipe[0] != -1)
     696            maxFd = qMax(maxFd, stdoutChannel.pipe[0]);
     697        }
     698        if (stderrChannel.pipe[0] != -1) {
    663699            FD_SET(stderrChannel.pipe[0], &fdread);
    664 
    665         if (!writeBuffer.isEmpty() && stdinChannel.pipe[1] != -1)
     700            maxFd = qMax(maxFd, stderrChannel.pipe[0]);
     701        }
     702
     703        if (!writeBuffer.isEmpty() && stdinChannel.pipe[1] != -1) {
    666704            FD_SET(stdinChannel.pipe[1], &fdwrite);
     705
     706
    667707
    668708        int timeout = qt_timeout_value(msecs, stopWatch.elapsed());
    669         int ret = qt_select(&fdread, &fdwrite, timeout);
     709        int ret;
     710        if (maxFd >= 0) {
     711            ret = qt_select(maxFd + 1, &fdread, &fdwrite, timeout);
     712        } else {
     713            int exitStatus;
     714            ret = waitpid(pid, &exitStatus, 0);
     715        }
    670716        if (ret < 0) {
    671717            break;
     
    712758        FD_ZERO(&fdwrite);
    713759
    714         if (stdoutChannel.pipe[0] != -1)
     760        int maxFd = -1;
     761        if (stdoutChannel.pipe[0] != -1) {
    715762            FD_SET(stdoutChannel.pipe[0], &fdread);
    716         if (stderrChannel.pipe[0] != -1)
     763            maxFd = qMax(maxFd, stdoutChannel.pipe[0]);
     764        }
     765        if (stderrChannel.pipe[0] != -1) {
    717766            FD_SET(stderrChannel.pipe[0], &fdread);
    718 
    719         if (!writeBuffer.isEmpty() && stdinChannel.pipe[1] != -1)
     767            maxFd = qMax(maxFd, stderrChannel.pipe[0]);
     768        }
     769
     770        if (!writeBuffer.isEmpty() && stdinChannel.pipe[1] != -1) {
    720771            FD_SET(stdinChannel.pipe[1], &fdwrite);
     772
     773
    721774
    722775        int timeout = qt_timeout_value(msecs, stopWatch.elapsed());
    723         int ret = qt_select(&fdread, &fdwrite, timeout);
     776        int ret;
     777        if (maxFd >= 0) {
     778            ret = qt_select(maxFd + 1, &fdread, &fdwrite, timeout);
     779        } else {
     780            int exitStatus;
     781            ret = waitpid(pid, &exitStatus, 0);
     782        }
    724783        if (ret < 0) {
    725784            break;
     
    754813    FD_SET(stdinChannel.pipe[1], &fdwrite);
    755814
    756     int ret = qt_select(0, &fdwrite, msecs < 0 ? 0 : msecs) == 1;
     815    int ret = qt_select(stdinChannel.pipe[1] + 1, 0, &fdwrite,
     816                        msecs < 0 ? 0 : msecs) == 1;
    757817    return ret == 1;
    758818}
Note: See TracChangeset for help on using the changeset viewer.