summaryrefslogtreecommitdiff
path: root/core/launcher/qprocess_unix.cpp
Side-by-side diff
Diffstat (limited to 'core/launcher/qprocess_unix.cpp') (more/less context) (ignore whitespace changes)
-rw-r--r--core/launcher/qprocess_unix.cpp6
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;
}