Changeset 918


Ignore:
Timestamp:
Jul 31, 2011, 6:41:23 PM (9 years ago)
Author:
Dmitry A. Kuminov
Message:

OS/2: QProcess: Use dup()/dup2() instead of DosDupHandle?().

This fixes broken state of the stdin/out/err handles in the child process
(e.g. isatty() returning 1 while they are actually pipes, etc.). dup()/dup2()
are LIBC functions and hence know how to play with LIBC handles, as
opposed to DosDupHandle?().

File:
1 edited

Legend:

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

    r913 r918  
    457457        // same pipe key may be mixed. We need CLOSE messages to be posted after
    458458        // READ messages, so we do two passes.
    459        
     459
    460460        // @todo We don't need two passes any more!
    461461
     
    10871087    q->setProcessState(QProcess::Starting);
    10881088
    1089     APIRET arc;
     1089    int rc;
    10901090
    10911091    QString error;
    1092     HFILE tmpStdin = HFILE(~0), tmpStdout = HFILE(~0), tmpStderr = HFILE(~0);
    1093     HFILE realStdin = HF_STDIN, realStdout = HF_STDOUT, realStderr = HF_STDERR;
     1092    int tmpStdin = -1, tmpStdout = -1, tmpStderr = -1;
     1093    int realStdin = fileno(stdin), realStdout = fileno(stdout),
     1094        realStderr = fileno(stderr);
    10941095
    10951096    do {
    10961097        // save & copy the stdin handle
    1097         if ((arc = DosDupHandle(realStdin, &tmpStdin)) == NO_ERROR) {
     1098        if ((rc = tmpStdin = dup(realStdin)) != -1) {
    10981099            HFILE handle = stdinChannel.pipe.client;
    10991100            if (stdinChannel.type == Channel::PipeSink) {
     
    11081109                Q_ASSERT(handle != HFILE(~0));
    11091110            }
    1110             arc = DosDupHandle(handle, &realStdin);
    1111         }
    1112         if (arc != NO_ERROR) {
    1113             DEBUG(("QProcessPrivate::startProcess: DosDupHandle for STDIN "
    1114                    "returned %lu", arc));
     1111            Q_ASSERT(_imphandle(handle) != -1);
     1112            rc = dup2(_imphandle(handle), realStdin);
     1113        }
     1114        if (rc == -1) {
     1115            DEBUG(("QProcessPrivate::startProcess: dup/dup2 for stdin "
     1116                   "failed with %d (%s)", errno, strerror(errno)));
    11151117            break;
    11161118        }
     
    11181120        if (processChannelMode != QProcess::ForwardedChannels) {
    11191121            // save & copy the stdout handle
    1120             if ((arc = DosDupHandle(realStdout, &tmpStdout)) == NO_ERROR) {
     1122            if ((rc = tmpStdout = dup(realStdout)) != -1) {
    11211123                HFILE handle = stdoutChannel.pipe.client;
    11221124                if (stdoutChannel.type == Channel::PipeSource) {
     
    11311133                    Q_ASSERT(handle != HFILE(~0));
    11321134                }
    1133                 arc = DosDupHandle(handle, &realStdout);
    1134             }
    1135             if (arc != NO_ERROR) {
    1136                 DEBUG(("QProcessPrivate::startProcess: DosDupHandle for STDOUT "
    1137                        "returned %lu", arc));
     1135                Q_ASSERT(_imphandle(handle) != -1);
     1136                rc = dup2(_imphandle(handle), realStdout);
     1137            }
     1138            if (rc == -1) {
     1139                DEBUG(("QProcessPrivate::startProcess: dup/dup2 for stdout "
     1140                       "failed with %d (%s)", errno, strerror(errno)));
    11381141                break;
    11391142            }
    1140             if ((arc = DosDupHandle(realStderr, &tmpStderr)) == NO_ERROR) {
     1143            if ((rc = tmpStderr = dup(realStderr)) != -1) {
    11411144                // merge stdout and stderr if asked to
    11421145                if (processChannelMode == QProcess::MergedChannels) {
    1143                     arc = DosDupHandle(realStdout, &realStderr);
     1146                    rc = dup2(realStdout, realStderr);
    11441147                } else {
    1145                     arc = DosDupHandle(stderrChannel.pipe.client, &realStderr);
     1148                    HFILE handle = stderrChannel.pipe.client;
     1149                    Q_ASSERT(_imphandle(handle) != -1);
     1150                    rc = dup2(_imphandle(handle), realStderr);
    11461151                }
    11471152            }
    1148             if (arc != NO_ERROR)
     1153            if (rc == -1) {
     1154                DEBUG(("QProcessPrivate::startProcess: dup/dup2 for stderr "
     1155                       "failed with %d (%s)", errno, strerror(errno)));
    11491156                break;
     1157            }
    11501158        }
    11511159
     
    11531161
    11541162    int pid = -1;
    1155     if (arc == NO_ERROR) {
     1163    if (rc != -1) {
    11561164        QStringList env = environment.toStringList();
    11571165        pid = qt_startProcess(program, arguments, workingDirectory, &env);
     
    11591167
    11601168    // cancel STDIN/OUT/ERR redirections
    1161     if (tmpStdin != HFILE(~0)) {
    1162         DosDupHandle(tmpStdin, &realStdin);
    1163         DosClose(tmpStdin);
    1164     }
    1165     if (tmpStdout != HFILE(~0)) {
    1166         DosDupHandle(tmpStdout, &realStdout);
    1167         DosClose(tmpStdout);
    1168     }
    1169     if ( tmpStderr != HFILE(~0)) {
    1170         DosDupHandle(tmpStderr, &realStderr);
    1171         DosClose(tmpStderr);
    1172     }
    1173 
    1174     if (arc != NO_ERROR || pid == -1) {
     1169    if (tmpStdin != -1) {
     1170        dup2(tmpStdin, realStdin);
     1171        close(tmpStdin);
     1172    }
     1173    if (tmpStdout != -1) {
     1174        dup2(tmpStdout, realStdout);
     1175        close(tmpStdout);
     1176    }
     1177    if ( tmpStderr != -1) {
     1178        dup2(tmpStderr, realStderr);
     1179        close(tmpStderr);
     1180    }
     1181
     1182    if (rc == -1 || pid == -1) {
    11751183        // Cleanup, report error and return
    11761184        q->setProcessState(QProcess::NotRunning);
    11771185        processError = QProcess::FailedToStart;
    1178         if (arc != NO_ERROR) {
     1186        if (rc == -1) {
    11791187            // handle duplication failed
    11801188            q->setErrorString(QProcess::tr("Process failed to start: %1")
    1181                                            .arg(QString(QLatin1String("DOS error %1"))
    1182                                                 .arg(arc)));
     1189                                           .arg(qt_error_string(errno)));
    11831190        } else {
    11841191            DEBUG(("spawnvpe failed: %s", qPrintable(qt_error_string(errno))));
Note: See TracChangeset for help on using the changeset viewer.