Diffstat (limited to 'core/launcher/qprocess_unix.cpp') (more/less context) (ignore whitespace changes)
-rw-r--r-- | core/launcher/qprocess_unix.cpp | 6 |
1 files changed, 5 insertions, 1 deletions
diff --git a/core/launcher/qprocess_unix.cpp b/core/launcher/qprocess_unix.cpp index 97c0460..3125bcc 100644 --- a/core/launcher/qprocess_unix.cpp +++ b/core/launcher/qprocess_unix.cpp @@ -220,193 +220,197 @@ QProcessManager::QProcessManager() this, SLOT(sigchldHnd(int)) ); sn->setEnabled( TRUE ); } // install a SIGCHLD handler and ignore SIGPIPE struct sigaction act; #if defined(QT_QPROCESS_DEBUG) odebug << "QProcessManager: install a SIGCHLD handler" << oendl; #endif act.sa_handler = qt_C_sigchldHnd; sigemptyset( &(act.sa_mask) ); sigaddset( &(act.sa_mask), SIGCHLD ); act.sa_flags = SA_NOCLDSTOP; #if defined(SA_RESTART) act.sa_flags |= SA_RESTART; #endif if ( sigaction( SIGCHLD, &act, &oldactChld ) != 0 ) owarn << "Error installing SIGCHLD handler" << oendl; #if defined(QT_QPROCESS_DEBUG) odebug << "QProcessManager: install a SIGPIPE handler (SIG_IGN)" << oendl; #endif /* Using qt_C_sigpipeHnd rather than SIG_IGN is a workaround for a strange problem where GNU tar (called by backuprestore) would hang on filesystem-full. Strangely, the qt_C_sigpipeHnd is never even called, yet this avoids the hang. */ act.sa_handler = qt_C_sigpipeHnd; sigemptyset( &(act.sa_mask) ); sigaddset( &(act.sa_mask), SIGPIPE ); act.sa_flags = 0; if ( sigaction( SIGPIPE, &act, &oldactPipe ) != 0 ) owarn << "Error installing SIGPIPE handler" << oendl; } QProcessManager::~QProcessManager() { delete procList; if ( sigchldFd[0] != 0 ) ::close( sigchldFd[0] ); if ( sigchldFd[1] != 0 ) ::close( sigchldFd[1] ); // restore SIGCHLD handler #if defined(QT_QPROCESS_DEBUG) odebug << "QProcessManager: restore old sigchild handler" << oendl; #endif if ( sigaction( SIGCHLD, &oldactChld, 0 ) != 0 ) owarn << "Error restoring SIGCHLD handler" << oendl; #if defined(QT_QPROCESS_DEBUG) odebug << "QProcessManager: restore old sigpipe handler" << oendl; #endif if ( sigaction( SIGPIPE, &oldactPipe, 0 ) != 0 ) owarn << "Error restoring SIGPIPE handler" << oendl; } void QProcessManager::append( QProc *p ) { procList->append( p ); #if defined(QT_QPROCESS_DEBUG) odebug << "QProcessManager: append process (procList.count(): " << procList->count() << ")" << oendl; #endif } void QProcessManager::remove( QProc *p ) { procList->remove( p ); #if defined(QT_QPROCESS_DEBUG) odebug << "QProcessManager: remove process (procList.count(): " << procList->count() << ")" << oendl; #endif cleanup(); } void QProcessManager::cleanup() { if ( procList->count() == 0 ) { QTimer::singleShot( 0, this, SLOT(removeMe()) ); } } void QProcessManager::removeMe() { if ( procList->count() == 0 ) { qprocess_cleanup_procmanager.remove( &QProcessPrivate::procManager ); QProcessPrivate::procManager = 0; delete this; } } void QProcessManager::sigchldHnd( int fd ) { char tmp; - ::read( fd, &tmp, sizeof(tmp) ); + if (::read( fd, &tmp, sizeof(tmp) ) < 0) +#if defined(QT_QPROCESS_DEBUG) + odebug << "QProcessManager::sigchldHnd() failed dummy read of file descriptor" << oendl; +#endif + ; #if defined(QT_QPROCESS_DEBUG) odebug << "QProcessManager::sigchldHnd()" << oendl; #endif QProc *proc; QProcess *process; bool removeProc; proc = procList->first(); while ( proc != 0 ) { removeProc = FALSE; process = proc->process; QProcess *process_exit_notify=0; if ( process != 0 ) { if ( !process->isRunning() ) { #if defined(QT_QPROCESS_DEBUG) odebug << "QProcessManager::sigchldHnd() (PID: " << proc->pid << "): process exited (QProcess available)" << oendl; #endif // read pending data int nbytes = 0; if ( ::ioctl(proc->socketStdout, FIONREAD, (char*)&nbytes)==0 && nbytes>0 ) { #if defined(QT_QPROCESS_DEBUG) odebug << "QProcessManager::sigchldHnd() (PID: " << proc->pid << "): reading " << nbytes << " bytes of pending data on stdout" << oendl; #endif process->socketRead( proc->socketStdout ); } nbytes = 0; if ( ::ioctl(proc->socketStderr, FIONREAD, (char*)&nbytes)==0 && nbytes>0 ) { #if defined(QT_QPROCESS_DEBUG) odebug << "QProcessManager::sigchldHnd() (PID: " << proc->pid << "): reading " << nbytes << " bytes of pending data on stderr" << oendl; #endif process->socketRead( proc->socketStderr ); } if ( process->notifyOnExit ) process_exit_notify = process; removeProc = TRUE; } } else { int status; if ( ::waitpid( proc->pid, &status, WNOHANG ) == proc->pid ) { #if defined(QT_QPROCESS_DEBUG) odebug << "QProcessManager::sigchldHnd() (PID: " << proc->pid << "): process exited (QProcess not available)" << oendl; #endif removeProc = TRUE; } } if ( removeProc ) { QProc *oldproc = proc; proc = procList->next(); remove( oldproc ); } else { proc = procList->next(); } if ( process_exit_notify ) emit process_exit_notify->processExited(); } } #include "qprocess_unix.moc" /*********************************************************************** * * QProcessPrivate * **********************************************************************/ QProcessManager *QProcessPrivate::procManager = 0; QProcessPrivate::QProcessPrivate() { #if defined(QT_QPROCESS_DEBUG) odebug << "QProcessPrivate: Constructor" << oendl; #endif stdinBufRead = 0; notifierStdin = 0; notifierStdout = 0; notifierStderr = 0; exitValuesCalculated = FALSE; socketReadCalled = FALSE; proc = 0; } QProcessPrivate::~QProcessPrivate() { #if defined(QT_QPROCESS_DEBUG) odebug << "QProcessPrivate: Destructor" << oendl; #endif if ( proc != 0 ) { if ( proc->socketStdin != 0 ) { ::close( proc->socketStdin ); proc->socketStdin = 0; } |