Changeset 73 for trunk/src


Ignore:
Timestamp:
Jul 9, 2009, 2:16:47 PM (16 years ago)
Author:
Dmitry A. Kuminov
Message:

corelib: OS/2: Implemented QProcess::startDetached().

File:
1 edited

Legend:

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

    r72 r73  
    243243}
    244244
    245 void QProcessPrivate::startProcess()
    246 {
    247     Q_Q(QProcess);
    248 
    249 #if defined (QPROCESS_DEBUG)
    250     qDebug("QProcessPrivate::startProcess()");
    251 #endif
    252 
    253     // Initialize pipes
    254     if (!createChannel(stdinChannel) ||
    255         !createChannel(stdoutChannel) ||
    256         !createChannel(stderrChannel))
    257         return;
    258 
    259     // Start the process (platform dependent)
    260     q->setProcessState(QProcess::Starting);
    261 
    262     // save & copy the stdin socket
    263     int stdin_copy = ::dup(fileno(stdin));
    264     ::dup2(stdinChannel.pipe[0], fileno(stdin));
    265 
    266     // save & copy the stdout and stderr if asked to
    267     int stdout_copy = -1, stderr_copy = -1;
    268     if (processChannelMode != QProcess::ForwardedChannels) {
    269         stdout_copy = ::dup(fileno(stdout));
    270         ::dup2(stdoutChannel.pipe[1], fileno(stdout));
    271 
    272         // merge stdout and stderr if asked to
    273         stderr_copy = ::dup(fileno(stderr));
    274         if (processChannelMode == QProcess::MergedChannels) {
    275             ::dup2(fileno(stdout), fileno(stderr));
    276         } else {
    277             ::dup2(stderrChannel.pipe[1], fileno(stderr));
    278         }
    279     }
     245static int qt_startProcess(const QString &program, const QStringList &arguments,
     246                           const QString &workingDirectory,
     247                           const QStringList *environment, bool detached = false)
     248{
     249    int mode = detached ? P_DETACH : P_NOWAIT;
    280250
    281251    // Create argument list with right number of elements, and set the final
     
    299269    int envc = 0;
    300270    char **envv;
    301     if (environment.count()) {
     271    if (environment && environment->count()) {
    302272        bool seenPATH = false;
    303273        bool seenCOMSPEC = false;
    304274
    305         envv = new char *[environment.count() + 1 + 2 /* may be PATH + COMSPEC */];
    306         for (; envc < environment.count(); ++envc) {
    307             QString item = environment.at(envc);
     275        envv = new char *[environment->count() + 1 + 2 /* may be PATH + COMSPEC */];
     276        for (; envc < environment->count(); ++envc) {
     277            QString item = environment->at(envc);
    308278            envv[envc] = qstrdup(item.toLocal8Bit().constData());
    309279            if (!seenPATH)
     
    340310
    341311    // start the program
    342     int pid = spawnvpe(P_NOWAIT | P_DEFAULT, encodedProgramName, argv, envv);
     312    int pid = spawnvpe(mode | P_DEFAULT, encodedProgramName, argv, envv);
    343313
    344314    // if spawnvpe() couldn't find the executable, try .CMD and .BAT
     
    368338    // restore the current directory
    369339    QDir::setCurrent(curDir);
     340
     341    return pid;
     342}
     343
     344void QProcessPrivate::startProcess()
     345{
     346    Q_Q(QProcess);
     347
     348#if defined (QPROCESS_DEBUG)
     349    qDebug("QProcessPrivate::startProcess()");
     350#endif
     351
     352    // Initialize pipes
     353    if (!createChannel(stdinChannel) ||
     354        !createChannel(stdoutChannel) ||
     355        !createChannel(stderrChannel))
     356        return;
     357
     358    // Start the process (platform dependent)
     359    q->setProcessState(QProcess::Starting);
     360
     361    // save & copy the stdin socket
     362    int stdin_copy = ::dup(fileno(stdin));
     363    ::dup2(stdinChannel.pipe[0], fileno(stdin));
     364
     365    // save & copy the stdout and stderr if asked to
     366    int stdout_copy = -1, stderr_copy = -1;
     367    if (processChannelMode != QProcess::ForwardedChannels) {
     368        stdout_copy = ::dup(fileno(stdout));
     369        ::dup2(stdoutChannel.pipe[1], fileno(stdout));
     370
     371        // merge stdout and stderr if asked to
     372        stderr_copy = ::dup(fileno(stderr));
     373        if (processChannelMode == QProcess::MergedChannels) {
     374            ::dup2(fileno(stdout), fileno(stderr));
     375        } else {
     376            ::dup2(stderrChannel.pipe[1], fileno(stderr));
     377        }
     378    }
     379
     380    int pid = qt_startProcess(program, arguments, workingDirectory,
     381                              &environment);
    370382
    371383    // restore stdin/stdout/stderr
     
    776788/*! \internal
    777789 */
    778 bool QProcessPrivate::startDetached(const QString &program, const QStringList &arguments, const QString &workingDirectory, qint64 *pid)
    779 {
    780 // @todo later
    781 #if 0
    782     processManager()->start();
    783 
    784     QByteArray encodedWorkingDirectory = QFile::encodeName(workingDirectory);
    785 
    786     // To catch the startup of the child
    787     int startedPipe[2];
    788     ::pipe(startedPipe);
    789     // To communicate the pid of the child
    790     int pidPipe[2];
    791     ::pipe(pidPipe);
    792 
    793     pid_t childPid = qt_fork();
    794     if (childPid == 0) {
    795         struct sigaction noaction;
    796         memset(&noaction, 0, sizeof(noaction));
    797         noaction.sa_handler = SIG_IGN;
    798         qt_native_sigaction(SIGPIPE, &noaction, 0);
    799 
    800         ::setsid();
    801 
    802         qt_native_close(startedPipe[0]);
    803         qt_native_close(pidPipe[0]);
    804 
    805         pid_t doubleForkPid = qt_fork();
    806         if (doubleForkPid == 0) {
    807             ::fcntl(startedPipe[1], F_SETFD, FD_CLOEXEC);
    808             qt_native_close(pidPipe[1]);
    809 
    810             if (!encodedWorkingDirectory.isEmpty())
    811                 qt_native_chdir(encodedWorkingDirectory.constData());
    812 
    813             char **argv = new char *[arguments.size() + 2];
    814             for (int i = 0; i < arguments.size(); ++i) {
    815 #ifdef Q_OS_MAC
    816                 argv[i + 1] = ::strdup(arguments.at(i).toUtf8().constData());
    817 #else
    818                 argv[i + 1] = ::strdup(arguments.at(i).toLocal8Bit().constData());
    819 #endif
    820             }
    821             argv[arguments.size() + 1] = 0;
    822 
    823             if (!program.contains(QLatin1Char('/'))) {
    824                 const QString path = QString::fromLocal8Bit(::getenv("PATH"));
    825                 if (!path.isEmpty()) {
    826                     QStringList pathEntries = path.split(QLatin1Char(':'));
    827                     for (int k = 0; k < pathEntries.size(); ++k) {
    828                         QByteArray tmp = QFile::encodeName(pathEntries.at(k));
    829                         if (!tmp.endsWith('/')) tmp += '/';
    830                         tmp += QFile::encodeName(program);
    831                         argv[0] = tmp.data();
    832                         qt_native_execv(argv[0], argv);
    833                     }
    834                 }
    835             } else {
    836                 QByteArray tmp = QFile::encodeName(program);
    837                 argv[0] = tmp.data();
    838                 qt_native_execv(argv[0], argv);
    839             }
    840 
    841             struct sigaction noaction;
    842             memset(&noaction, 0, sizeof(noaction));
    843             noaction.sa_handler = SIG_IGN;
    844             qt_native_sigaction(SIGPIPE, &noaction, 0);
    845 
    846             // '\1' means execv failed
    847             char c = '\1';
    848             qt_native_write(startedPipe[1], &c, 1);
    849             qt_native_close(startedPipe[1]);
    850             ::_exit(1);
    851         } else if (doubleForkPid == -1) {
    852             struct sigaction noaction;
    853             memset(&noaction, 0, sizeof(noaction));
    854             noaction.sa_handler = SIG_IGN;
    855             qt_native_sigaction(SIGPIPE, &noaction, 0);
    856 
    857             // '\2' means internal error
    858             char c = '\2';
    859             qt_native_write(startedPipe[1], &c, 1);
    860         }
    861 
    862         qt_native_close(startedPipe[1]);
    863         qt_native_write(pidPipe[1], (const char *)&doubleForkPid, sizeof(pid_t));
    864         qt_native_chdir("/");
    865         ::_exit(1);
    866     }
    867 
    868     qt_native_close(startedPipe[1]);
    869     qt_native_close(pidPipe[1]);
    870 
    871     if (childPid == -1) {
    872         qt_native_close(startedPipe[0]);
    873         qt_native_close(pidPipe[0]);
     790bool QProcessPrivate::startDetached(const QString &program, const QStringList &arguments,
     791                                    const QString &workingDirectory, qint64 *pid)
     792{
     793    int startedPid = qt_startProcess(program, arguments, workingDirectory,
     794                                     NULL, true /* detached */);
     795
     796    if (startedPid == -1)
    874797        return false;
    875     }
    876 
    877     char reply = '\0';
    878     int startResult = qt_native_read(startedPipe[0], &reply, 1);
    879     int result;
    880     qt_native_close(startedPipe[0]);
    881     while (::waitpid(childPid, &result, 0) == -1 && errno == EINTR)
    882     { }
    883     bool success = (startResult != -1 && reply == '\0');
    884     if (success && pid) {
    885         pid_t actualPid = 0;
    886         if (qt_native_read(pidPipe[0], (char *)&actualPid, sizeof(pid_t)) == sizeof(pid_t)) {
    887             *pid = actualPid;
    888         } else {
    889             *pid = 0;
    890         }
    891     }
    892     qt_native_close(pidPipe[0]);
    893     return success;
    894 #endif
     798
     799    *pid = startedPid;
     800    return true;
    895801}
    896802
Note: See TracChangeset for help on using the changeset viewer.