📄 qprocess_unix.cpp
字号:
d->notifierStderr = new QSocketNotifier( sStderr[0], QSocketNotifier::Read ); connect( d->notifierStderr, SIGNAL(activated(int)), this, SLOT(socketRead(int)) ); if ( ioRedirection ) d->notifierStderr->setEnabled( TRUE ); } // cleanup and return delete[] arglistQ; delete[] arglist; return TRUE;error:#if defined(QT_QPROCESS_DEBUG) qDebug( "QProcess::start(): error starting process" );#endif if ( d->procManager ) d->procManager->cleanup(); if ( comms & Stdin ) { ::close( sStdin[1] ); ::close( sStdin[0] ); } if ( comms & Stdout ) { ::close( sStdout[0] ); ::close( sStdout[1] ); } if ( comms & Stderr ) { ::close( sStderr[0] ); ::close( sStderr[1] ); } ::close( fd[0] ); ::close( fd[1] ); delete[] arglistQ; delete[] arglist; return FALSE;}/*! Asks the process to terminate. Processes can ignore this wish. If you want to be sure that the process really terminates, you must use kill() instead. The slot returns immediately: it does not wait until the process has finished. When the process really exited, the signal processExited() is emitted. \sa kill() processExited()*/void QProcess::tryTerminate() const{ if ( d->proc != 0 ) ::kill( d->proc->pid, SIGTERM );}/*! Terminates the process. This is not a safe way to end a process since the process will not be able to do cleanup. tryTerminate() is a safer way to do it, but processes might ignore a tryTerminate(). The nice way to end a process and to be sure that it is finished, is doing something like this: \code process->tryTerminate(); QTimer::singleShot( 5000, process, SLOT( kill() ) ); \endcode This tries to terminate the process the nice way. If the process is still running after 5 seconds, it terminates the process the hard way. The timeout should be chosen depending on the time the process needs to do all the cleanup: use a higher value if the process is likely to do heavy computation on cleanup. The slot returns immediately: it does not wait until the process has finished. When the process really exited, the signal processExited() is emitted. \sa tryTerminate() processExited()*/void QProcess::kill() const{ if ( d->proc != 0 ) ::kill( d->proc->pid, SIGKILL );}/*! Returns TRUE if the process is running, otherwise FALSE. \sa normalExit() exitStatus() processExited()*/bool QProcess::isRunning() const{ if ( d->exitValuesCalculated ) {#if defined(QT_QPROCESS_DEBUG) qDebug( "QProcess::isRunning(): FALSE (already computed)" );#endif return FALSE; } if ( d->proc == 0 ) return FALSE; int status; if ( ::waitpid( d->proc->pid, &status, WNOHANG ) == d->proc->pid ) { // compute the exit values QProcess *that = (QProcess*)this; // mutable that->exitNormal = WIFEXITED( status ) != 0; if ( exitNormal ) { that->exitStat = (char)WEXITSTATUS( status ); } d->exitValuesCalculated = TRUE;#if defined(QT_QPROCESS_DEBUG) qDebug( "QProcess::isRunning() (PID: %d): FALSE", d->proc->pid );#endif return FALSE; }#if defined(QT_QPROCESS_DEBUG) qDebug( "QProcess::isRunning() (PID: %d): TRUE", d->proc->pid );#endif return TRUE;}/*! Writes the data \a buf to the standard input of the process. The process may or may not read this data. This function returns immediately; the QProcess class might write the data at a later point (you have to enter the event loop for that). When all the data is written to the process, the signal wroteToStdin() is emitted. This does not mean that the process really read the data, since this class only detects when it was able to write the data to the operating system. \sa wroteToStdin() closeStdin() readStdout() readStderr()*/void QProcess::writeToStdin( const QByteArray& buf ){#if defined(QT_QPROCESS_DEBUG)// qDebug( "QProcess::writeToStdin(): write to stdin (%d)", d->socketStdin );#endif d->stdinBuf.enqueue( new QByteArray(buf) ); if ( d->notifierStdin != 0 ) d->notifierStdin->setEnabled( TRUE );}/*! Closes standard input of the process. This function also deletes pending data that is not written to standard input yet. \sa wroteToStdin()*/void QProcess::closeStdin(){ if ( d->proc == 0 ) return; if ( d->proc->socketStdin !=0 ) { while ( !d->stdinBuf.isEmpty() ) { delete d->stdinBuf.dequeue(); } delete d->notifierStdin; d->notifierStdin = 0; if ( ::close( d->proc->socketStdin ) != 0 ) { qWarning( "Could not close stdin of child process" ); }#if defined(QT_QPROCESS_DEBUG) qDebug( "QProcess::closeStdin(): stdin (%d) closed", d->proc->socketStdin );#endif d->proc->socketStdin = 0; }}/* This private slot is called when the process has outputted data to either standard output or standard error.*/void QProcess::socketRead( int fd ){ if ( d->socketReadCalled ) { // the slots that are connected to the readyRead...() signals might // trigger a recursive call of socketRead(). Avoid this since you get a // blocking read otherwise. return; }#if defined(QT_QPROCESS_DEBUG) qDebug( "QProcess::socketRead(): %d", fd );#endif if ( fd == 0 ) return; const int bufsize = 4096; QByteArray *buffer = 0; uint oldSize; int n; if ( fd == d->proc->socketStdout ) { buffer = &d->bufStdout; } else if ( fd == d->proc->socketStderr ) { buffer = &d->bufStderr; } else { // this case should never happen, but just to be safe return; } // read data oldSize = buffer->size(); buffer->resize( oldSize + bufsize ); n = ::read( fd, buffer->data()+oldSize, bufsize ); if ( n > 0 ) buffer->resize( oldSize + n ); else buffer->resize( oldSize ); // eof or error? if ( n == 0 || n == -1 ) { if ( fd == d->proc->socketStdout ) {#if defined(QT_QPROCESS_DEBUG) qDebug( "QProcess::socketRead(): stdout (%d) closed", fd );#endif d->notifierStdout->setEnabled( FALSE ); delete d->notifierStdout; d->notifierStdout = 0; ::close( d->proc->socketStdout ); d->proc->socketStdout = 0; return; } else if ( fd == d->proc->socketStderr ) {#if defined(QT_QPROCESS_DEBUG) qDebug( "QProcess::socketRead(): stderr (%d) closed", fd );#endif d->notifierStderr->setEnabled( FALSE ); delete d->notifierStderr; d->notifierStderr = 0; ::close( d->proc->socketStderr ); d->proc->socketStderr = 0; return; } } // read all data that is available while ( n == bufsize ) { oldSize = buffer->size(); buffer->resize( oldSize + bufsize ); n = ::read( fd, buffer->data()+oldSize, bufsize ); if ( n > 0 ) buffer->resize( oldSize + n ); else buffer->resize( oldSize ); } d->socketReadCalled = TRUE; if ( fd == d->proc->socketStdout ) {#if defined(QT_QPROCESS_DEBUG) qDebug( "QProcess::socketRead(): %d bytes read from stdout (%d)", buffer->size()-oldSize, fd );#endif emit readyReadStdout(); } else if ( fd == d->proc->socketStderr ) {#if defined(QT_QPROCESS_DEBUG) qDebug( "QProcess::socketRead(): %d bytes read from stderr (%d)", buffer->size()-oldSize, fd );#endif emit readyReadStderr(); } d->socketReadCalled = FALSE;}/* This private slot is called when the process tries to write data to standard input of the child process.*/void QProcess::socketWrite( int fd ){ if ( fd != d->proc->socketStdin || d->proc->socketStdin == 0 ) return; if ( d->stdinBuf.isEmpty() ) { d->notifierStdin->setEnabled( FALSE ); return; }#if defined(QT_QPROCESS_DEBUG) qDebug( "QProcess::socketWrite(): write to stdin (%d)", fd );#endif ssize_t ret = ::write( fd, d->stdinBuf.head()->data() + d->stdinBufRead, d->stdinBuf.head()->size() - d->stdinBufRead ); if ( ret > 0 ) d->stdinBufRead += ret; else if ( ret < 0 && errno == EPIPE ) { // turn off the socket notifier and discard the remaining data // because the pipe has been disconnected on the remote end. d->notifierStdin->setEnabled( FALSE ); d->stdinBufRead = (ssize_t)d->stdinBuf.head()->size(); } if ( d->stdinBufRead == (ssize_t)d->stdinBuf.head()->size() ) { d->stdinBufRead = 0; delete d->stdinBuf.dequeue(); if ( wroteToStdinConnected && d->stdinBuf.isEmpty() ) emit wroteToStdin(); socketWrite( fd ); }}/*! \internal Flushes standard input. This is useful if you want to use QProcess in a synchronous manner. This function should probably go into the public API.*/void QProcess::flushStdin(){ socketWrite( d->proc->socketStdin );}/* This private slot is only used under Windows (but moc does not know about #if defined()).*/void QProcess::timeout(){}/* This private function is used by connectNotify() and disconnectNotify() to change the value of ioRedirection (and related behaviour)*/void QProcess::setIoRedirection( bool value ){ ioRedirection = value; if ( ioRedirection ) { if ( d->notifierStdout ) d->notifierStdout->setEnabled( TRUE ); if ( d->notifierStderr ) d->notifierStderr->setEnabled( TRUE ); } else { if ( d->notifierStdout ) d->notifierStdout->setEnabled( FALSE ); if ( d->notifierStderr ) d->notifierStderr->setEnabled( FALSE ); }}/* This private function is used by connectNotify() and disconnectNotify() to change the value of notifyOnExit (and related behaviour)*/void QProcess::setNotifyOnExit( bool value ){ notifyOnExit = value;}/* This private function is used by connectNotify() and disconnectNotify() to change the value of wroteToStdinConnected (and related behaviour)*/void QProcess::setWroteStdinConnected( bool value ){ wroteToStdinConnected = value;}/*! \enum QProcess::PID \internal*//*! Returns platform dependent information about the process. This can be used together with platform specific system calls. Under Unix the return value is the PID of the process, or -1 if no process is belonging to this object. Under Windows it is a pointer to the \c PROCESS_INFORMATION struct, or 0 if no process is belonging to this object.*/QProcess::PID QProcess::processIdentifier(){ if ( d->proc == 0 ) return -1; return d->proc->pid;}int QProcess::priority() const{ if ( d->proc ) return getpriority(PRIO_PROCESS,d->proc->pid); return 0;}/*! Sets the process priority to \a p, a value from -20 to 20, where 0 is normal, lower values a give more favourable priority, larger values less favourable.*/void QProcess::setPriority(int p){ if ( d->proc ) setpriority(PRIO_PROCESS,d->proc->pid,p);}#endif // QT_NO_PROCESS
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -