- Timestamp:
- Jul 9, 2009, 2:16:47 PM (16 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/corelib/io/qprocess_os2.cpp
r72 r73 243 243 } 244 244 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 } 245 static 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; 280 250 281 251 // Create argument list with right number of elements, and set the final … … 299 269 int envc = 0; 300 270 char **envv; 301 if (environment .count()) {271 if (environment && environment->count()) { 302 272 bool seenPATH = false; 303 273 bool seenCOMSPEC = false; 304 274 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); 308 278 envv[envc] = qstrdup(item.toLocal8Bit().constData()); 309 279 if (!seenPATH) … … 340 310 341 311 // start the program 342 int pid = spawnvpe( P_NOWAIT| P_DEFAULT, encodedProgramName, argv, envv);312 int pid = spawnvpe(mode | P_DEFAULT, encodedProgramName, argv, envv); 343 313 344 314 // if spawnvpe() couldn't find the executable, try .CMD and .BAT … … 368 338 // restore the current directory 369 339 QDir::setCurrent(curDir); 340 341 return pid; 342 } 343 344 void 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); 370 382 371 383 // restore stdin/stdout/stderr … … 776 788 /*! \internal 777 789 */ 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]); 790 bool 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) 874 797 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; 895 801 } 896 802
Note:
See TracChangeset
for help on using the changeset viewer.