Changeset 192 for trunk/src


Ignore:
Timestamp:
Sep 24, 2009, 6:09:44 AM (16 years ago)
Author:
Dmitry A. Kuminov
Message:

corelib: QProcess: Implemented child termination/death detection for synchronous waitFor() methods.

Location:
trunk/src/corelib/io
Files:
2 edited

Legend:

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

    r191 r192  
    338338
    339339#if defined (QPROCESS_DEBUG)
    340     qDebug() << "QProcessManager::run() signaled";
     340    qDebug() << "QProcessManager::run() signaled";
    341341#endif
    342342        foreach (QProcess *proc, processes) {
    343             QMetaObject::invokeMethod(proc, "_q_processDied", Qt::QueuedConnection);
    344         }
    345 
     343            QProcessPrivate::WaitMode mode = (QProcessPrivate::WaitMode)
     344                proc->d_func()->waitMode.fetchAndStoreAcquire(QProcessPrivate::SigChild);
     345            switch (mode) {
     346            case QProcessPrivate::Select:
     347                ::so_cancel(proc->d_func()->maxSelectFd);
     348                break;
     349            case QProcessPrivate::Semaphore:
     350                DosPostEventSem(proc->d_func()->waitSem);
     351                break;
     352            case QProcessPrivate::Async:
     353            case QProcessPrivate::SigChild:
     354                QMetaObject::invokeMethod(proc, "_q_processDied", Qt::QueuedConnection);
     355                break;
     356            }
     357        }
    346358    } while (true);
    347359
     
    354366void QProcessPrivate::init()
    355367{
     368
     369
     370
    356371    QProcessManager::addRef();
    357372}
     
    360375{
    361376    QProcessManager::release();
     377
     378
     379
     380
     381
     382
     383
     384
     385
     386
    362387}
    363388
     
    872897        }
    873898
    874         int timeout = qt_timeout_value(msecs, stopWatch.elapsed());
    875         int ret;
     899        WaitMode mode;
    876900        if (maxFd >= 0) {
    877             ret = qt_select(maxFd + 1, &fdread, &fdwrite, timeout);
     901            mode = Select;
     902            maxSelectFd = maxFd;
    878903        } else {
    879             int exitStatus;
    880             ret = waitpid(pid, &exitStatus, 0);
    881         }
    882         if (ret < 0) {
     904            mode = Semaphore;
     905            ensureWaitSem();
     906        }
     907
     908        bool timedOut = false, failed = false;
     909
     910        if (waitMode.testAndSetRelease(Async, mode)) {
     911            int timeout = qt_timeout_value(msecs, stopWatch.elapsed());
     912            if (maxFd >= 0) {
     913                int ret = qt_select(maxFd + 1, &fdread, &fdwrite, timeout);
     914                if (ret < 0 && errno != EINTR) {
     915                    Q_ASSERT(errno == EINTR);
     916                    failed = true;
     917                } else if (ret == 0) {
     918                    timedOut = true;
     919                } else if (ret >= 0) {
     920                    bool readyReadEmitted = false;
     921                    if (stdoutChannel.pipe[0] != -1 && FD_ISSET(stdoutChannel.pipe[0], &fdread)) {
     922                        bool canRead = _q_canReadStandardOutput();
     923                        if (processChannel == QProcess::StandardOutput && canRead)
     924                            readyReadEmitted = true;
     925                    }
     926                    if (stderrChannel.pipe[0] != -1 && FD_ISSET(stderrChannel.pipe[0], &fdread)) {
     927                        bool canRead = _q_canReadStandardError();
     928                        if (processChannel == QProcess::StandardError && canRead)
     929                            readyReadEmitted = true;
     930                    }
     931                    if (readyReadEmitted) {
     932                        waitMode.fetchAndStoreRelaxed(Async);
     933                        return true;
     934                    }
     935
     936                    if (stdinChannel.pipe[1] != -1 && FD_ISSET(stdinChannel.pipe[1], &fdwrite))
     937                        _q_canWrite();
     938
     939                    if (!pid)
     940                        failed = true;
     941                }
     942            } else {
     943                APIRET arc = DosWaitEventSem(waitSem, (ULONG)timeout);
     944                if (arc == ERROR_TIMEOUT) {
     945                    timedOut = true;
     946                } else if (arc != NO_ERROR) {
     947                    Q_ASSERT(arc == NO_ERROR);
     948                    failed = true;
     949                }
     950            }
     951        } else {
     952            // we've got SIGCHLD, proceeed to _q_processDied()
     953        }
     954
     955        waitMode.fetchAndStoreRelaxed(Async);
     956
     957        if (timedOut || failed) {
     958            if (timedOut) {
     959                processError = QProcess::Timedout;
     960                q->setErrorString(QProcess::tr("Process operation timed out"));
     961            }
    883962            break;
    884963        }
    885         if (ret == 0) {
    886             processError = QProcess::Timedout;
    887             q->setErrorString(QProcess::tr("Process operation timed out"));
    888             return false;
    889         }
    890 
    891         bool readyReadEmitted = false;
    892         if (stdoutChannel.pipe[0] != -1 && FD_ISSET(stdoutChannel.pipe[0], &fdread)) {
    893             bool canRead = _q_canReadStandardOutput();
    894             if (processChannel == QProcess::StandardOutput && canRead)
    895                 readyReadEmitted = true;
    896         }
    897         if (stderrChannel.pipe[0] != -1 && FD_ISSET(stderrChannel.pipe[0], &fdread)) {
    898             bool canRead = _q_canReadStandardError();
    899             if (processChannel == QProcess::StandardError && canRead)
    900                 readyReadEmitted = true;
    901         }
    902         if (readyReadEmitted)
    903             return true;
    904 
    905         if (stdinChannel.pipe[1] != -1 && FD_ISSET(stdinChannel.pipe[1], &fdwrite))
    906             _q_canWrite();
    907 
    908         if (!pid)
    909             return false;
     964
    910965        if (_q_processDied())
    911966            return false;
     
    9461001        }
    9471002
    948         int timeout = qt_timeout_value(msecs, stopWatch.elapsed());
    949         int ret;
     1003        WaitMode mode;
    9501004        if (maxFd >= 0) {
    951             ret = qt_select(maxFd + 1, &fdread, &fdwrite, timeout);
     1005            mode = Select;
     1006            maxSelectFd = maxFd;
    9521007        } else {
    953             int exitStatus;
    954             ret = waitpid(pid, &exitStatus, 0);
    955         }
    956         if (ret < 0) {
     1008            mode = Semaphore;
     1009            ensureWaitSem();
     1010        }
     1011
     1012        bool timedOut = false, failed = false;
     1013
     1014        if (waitMode.testAndSetRelease(Async, mode)) {
     1015            int timeout = qt_timeout_value(msecs, stopWatch.elapsed());
     1016            if (maxFd >= 0) {
     1017                int ret = qt_select(maxFd + 1, &fdread, &fdwrite, timeout);
     1018                if (ret < 0 && errno != EINTR) {
     1019                    Q_ASSERT(errno == EINTR);
     1020                    failed = true;
     1021                } else if (ret == 0) {
     1022                    timedOut = true;
     1023                } else if (ret >= 0) {
     1024                    if (stdinChannel.pipe[1] != -1 && FD_ISSET(stdinChannel.pipe[1], &fdwrite))
     1025                        return _q_canWrite();
     1026
     1027                    if (stdoutChannel.pipe[0] != -1 && FD_ISSET(stdoutChannel.pipe[0], &fdread))
     1028                        _q_canReadStandardOutput();
     1029
     1030                    if (stderrChannel.pipe[0] != -1 && FD_ISSET(stderrChannel.pipe[0], &fdread))
     1031                        _q_canReadStandardError();
     1032
     1033                    if (!pid)
     1034                        failed = true;
     1035                }
     1036            } else {
     1037                APIRET arc = DosWaitEventSem(waitSem, (ULONG)timeout);
     1038                if (arc == ERROR_TIMEOUT) {
     1039                    timedOut = true;
     1040                } else if (arc != NO_ERROR) {
     1041                    Q_ASSERT(arc == NO_ERROR);
     1042                    failed = true;
     1043                }
     1044            }
     1045        } else {
     1046            // we've got SIGCHLD, proceeed to _q_processDied()
     1047        }
     1048
     1049        waitMode.fetchAndStoreRelaxed(Async);
     1050
     1051        if (timedOut || failed) {
     1052            if (timedOut) {
     1053                processError = QProcess::Timedout;
     1054                q->setErrorString(QProcess::tr("Process operation timed out"));
     1055            }
    9571056            break;
    9581057        }
    959         if (ret == 0) {
    960             processError = QProcess::Timedout;
    961             q->setErrorString(QProcess::tr("Process operation timed out"));
    962             return false;
    963         }
    964 
    965         if (stdinChannel.pipe[1] != -1 && FD_ISSET(stdinChannel.pipe[1], &fdwrite))
    966             return _q_canWrite();
    967 
    968         if (stdoutChannel.pipe[0] != -1 && FD_ISSET(stdoutChannel.pipe[0], &fdread))
    969             _q_canReadStandardOutput();
    970 
    971         if (stderrChannel.pipe[0] != -1 && FD_ISSET(stderrChannel.pipe[0], &fdread))
    972             _q_canReadStandardError();
    973 
    974         if (!pid)
    975             return false;
     1058
    9761059        if (_q_processDied())
    9771060            return false;
     
    10131096        }
    10141097
    1015         int timeout = qt_timeout_value(msecs, stopWatch.elapsed());
    1016         int ret;
     1098        WaitMode mode;
    10171099        if (maxFd >= 0) {
    1018             ret = qt_select(maxFd + 1, &fdread, &fdwrite, timeout);
     1100            mode = Select;
     1101            maxSelectFd = maxFd;
    10191102        } else {
    1020             int exitStatus;
    1021             ret = waitpid(pid, &exitStatus, 0);
    1022         }
    1023         if (ret < 0) {
     1103            mode = Semaphore;
     1104            ensureWaitSem();
     1105        }
     1106
     1107        bool timedOut = false, failed = false;
     1108
     1109        if (waitMode.testAndSetRelease(Async, mode)) {
     1110            int timeout = qt_timeout_value(msecs, stopWatch.elapsed());
     1111            if (maxFd >= 0) {
     1112                int ret = qt_select(maxFd + 1, &fdread, &fdwrite, timeout);
     1113                if (ret < 0 && errno != EINTR) {
     1114                    Q_ASSERT(errno == EINTR);
     1115                    failed = true;
     1116                } else if (ret == 0) {
     1117                    timedOut = true;
     1118                } else if (ret >= 0) {
     1119                    if (stdinChannel.pipe[1] != -1 && FD_ISSET(stdinChannel.pipe[1], &fdwrite))
     1120                        _q_canWrite();
     1121
     1122                    if (stdoutChannel.pipe[0] != -1 && FD_ISSET(stdoutChannel.pipe[0], &fdread))
     1123                        _q_canReadStandardOutput();
     1124
     1125                    if (stderrChannel.pipe[0] != -1 && FD_ISSET(stderrChannel.pipe[0], &fdread))
     1126                        _q_canReadStandardError();
     1127
     1128                    if (!pid) {
     1129                        waitMode.fetchAndStoreRelaxed(Async);
     1130                        return true;
     1131                    }
     1132                }
     1133            } else {
     1134                APIRET arc = DosWaitEventSem(waitSem, (ULONG)timeout);
     1135                if (arc == ERROR_TIMEOUT) {
     1136                    timedOut = true;
     1137                } else if (arc != NO_ERROR) {
     1138                    Q_ASSERT(arc == NO_ERROR);
     1139                    failed = true;
     1140                }
     1141            }
     1142        } else {
     1143            // we've got SIGCHLD, proceeed to _q_processDied()
     1144        }
     1145
     1146        waitMode.fetchAndStoreRelaxed(Async);
     1147
     1148        if (timedOut || failed) {
     1149            if (timedOut) {
     1150                processError = QProcess::Timedout;
     1151                q->setErrorString(QProcess::tr("Process operation timed out"));
     1152            }
    10241153            break;
    10251154        }
    1026         if (ret == 0) {
    1027             processError = QProcess::Timedout;
    1028             q->setErrorString(QProcess::tr("Process operation timed out"));
    1029             return false;
    1030         }
    1031 
    1032         if (stdinChannel.pipe[1] != -1 && FD_ISSET(stdinChannel.pipe[1], &fdwrite))
    1033             _q_canWrite();
    1034 
    1035         if (stdoutChannel.pipe[0] != -1 && FD_ISSET(stdoutChannel.pipe[0], &fdread))
    1036             _q_canReadStandardOutput();
    1037 
    1038         if (stderrChannel.pipe[0] != -1 && FD_ISSET(stderrChannel.pipe[0], &fdread))
    1039             _q_canReadStandardError();
    1040 
    1041         if (!pid)
    1042             return true;
     1155
    10431156        if (_q_processDied())
    10441157            return true;
     
    10531166    FD_SET(stdinChannel.pipe[1], &fdwrite);
    10541167
    1055     int ret = qt_select(stdinChannel.pipe[1] + 1, 0, &fdwrite,
     1168    bool ret = false;
     1169    maxSelectFd = stdinChannel.pipe[1];
     1170    if (waitMode.testAndSetRelease(Async, Select)) {
     1171        ret = qt_select(stdinChannel.pipe[1] + 1, 0, &fdwrite,
    10561172                        msecs < 0 ? 0 : msecs) == 1;
    1057     return ret == 1;
     1173    }
     1174    waitMode.fetchAndStoreRelaxed(Async);
     1175    return ret;
    10581176}
    10591177
  • trunk/src/corelib/io/qprocess_p.h

    r190 r192  
    6666typedef int Q_PIPE;
    6767#define INVALID_Q_PIPE -1
     68
     69
     70
     71
    6872#endif
    6973
     
    198202    void init();
    199203    void uninit();
     204
    200205#endif
    201206
     
    209214    int serial;
    210215#endif
     216
     217
     218
     219
     220
     221
    211222
    212223    bool waitForStarted(int msecs = 30000);
Note: See TracChangeset for help on using the changeset viewer.