Q3ProcessManager Class Reference

Inheritance diagram for Q3ProcessManager:

Inheritance graph
[legend]
Collaboration diagram for Q3ProcessManager:

Collaboration graph
[legend]
List of all members.

Detailed Description

Definition at line 161 of file q3process_unix.cpp.

Public Slots

void removeMe ()
void sigchldHnd (int)

Public Member Functions

 Q3ProcessManager ()
 ~Q3ProcessManager ()
void append (QProc *p)
void remove (QProc *p)
void cleanup ()

Public Attributes

sigaction oldactChld
sigaction oldactPipe
Q3PtrList< QProc > * procList
int sigchldFd [2]

Private Attributes

QSocketNotifiersn


Constructor & Destructor Documentation

Q3ProcessManager::Q3ProcessManager (  ) 

Definition at line 243 of file q3process_unix.cpp.

References QObject::connect(), oldactChld, oldactPipe, procList, qDebug(), qt_C_sigchldHnd(), qWarning(), QSocketNotifier::Read, Q3PtrCollection::setAutoDelete(), QSocketNotifier::setEnabled(), sigchldFd, sigchldHnd(), SIGNAL, SLOT, and sn.

00243                                    : sn(0)
00244 {
00245     procList = new Q3PtrList<QProc>;
00246     procList->setAutoDelete( true );
00247 
00248     // The SIGCHLD handler writes to a socket to tell the manager that
00249     // something happened. This is done to get the processing in sync with the
00250     // event reporting.
00251 #ifndef Q_OS_QNX6
00252     if ( ::socketpair( AF_UNIX, SOCK_STREAM, 0, sigchldFd ) ) {
00253 #else
00254     if ( qnx6SocketPairReplacement (sigchldFd) ) {
00255 #endif
00256   sigchldFd[0] = 0;
00257   sigchldFd[1] = 0;
00258     } else {
00259 #if defined(QT_Q3PROCESS_DEBUG)
00260   qDebug( "Q3ProcessManager: install socket notifier (%d)", sigchldFd[1] );
00261 #endif
00262   sn = new QSocketNotifier( sigchldFd[1],
00263     QSocketNotifier::Read, this );
00264   connect( sn, SIGNAL(activated(int)),
00265     this, SLOT(sigchldHnd(int)) );
00266   sn->setEnabled( true );
00267     }
00268 
00269     // install a SIGCHLD handler and ignore SIGPIPE
00270     struct sigaction act;
00271 
00272 #if defined(QT_Q3PROCESS_DEBUG)
00273     qDebug( "Q3ProcessManager: install a SIGCHLD handler" );
00274 #endif
00275     act.sa_handler = qt_C_sigchldHnd;
00276     sigemptyset( &(act.sa_mask) );
00277     sigaddset( &(act.sa_mask), SIGCHLD );
00278     act.sa_flags = SA_NOCLDSTOP;
00279 #if defined(SA_RESTART)
00280     act.sa_flags |= SA_RESTART;
00281 #endif
00282     if ( sigaction( SIGCHLD, &act, &oldactChld ) != 0 )
00283   qWarning( "Error installing SIGCHLD handler" );
00284 
00285 #if defined(QT_Q3PROCESS_DEBUG)
00286     qDebug( "Q3ProcessManager: install a SIGPIPE handler (SIG_IGN)" );
00287 #endif
00288     act.sa_handler = QT_SIGNAL_IGNORE;
00289     sigemptyset( &(act.sa_mask) );
00290     sigaddset( &(act.sa_mask), SIGPIPE );
00291     act.sa_flags = 0;
00292     if ( sigaction( SIGPIPE, &act, &oldactPipe ) != 0 )
00293   qWarning( "Error installing SIGPIPE handler" );
00294 }

Here is the call graph for this function:

Q3ProcessManager::~Q3ProcessManager (  ) 

Definition at line 296 of file q3process_unix.cpp.

References oldactChld, oldactPipe, procList, qDebug(), qWarning(), and sigchldFd.

00297 {
00298     delete procList;
00299 
00300     if ( sigchldFd[0] != 0 )
00301   ::close( sigchldFd[0] );
00302     if ( sigchldFd[1] != 0 )
00303   ::close( sigchldFd[1] );
00304 
00305     // restore SIGCHLD handler
00306 #if defined(QT_Q3PROCESS_DEBUG)
00307     qDebug( "Q3ProcessManager: restore old sigchild handler" );
00308 #endif
00309     if ( sigaction( SIGCHLD, &oldactChld, 0 ) != 0 )
00310   qWarning( "Error restoring SIGCHLD handler" );
00311 
00312 #if defined(QT_Q3PROCESS_DEBUG)
00313     qDebug( "Q3ProcessManager: restore old sigpipe handler" );
00314 #endif
00315     if ( sigaction( SIGPIPE, &oldactPipe, 0 ) != 0 )
00316   qWarning( "Error restoring SIGPIPE handler" );
00317 }

Here is the call graph for this function:


Member Function Documentation

void Q3ProcessManager::append ( QProc p  ) 

Definition at line 319 of file q3process_unix.cpp.

References Q3PtrList< type >::append(), Q3PtrList< type >::count(), p, procList, and qDebug().

Referenced by Q3ProcessPrivate::newProc().

00320 {
00321     procList->append( p );
00322 #if defined(QT_Q3PROCESS_DEBUG)
00323     qDebug( "Q3ProcessManager: append process (procList.count(): %d)", procList->count() );
00324 #endif
00325 }

Here is the call graph for this function:

void Q3ProcessManager::remove ( QProc p  ) 

Definition at line 327 of file q3process_unix.cpp.

References cleanup(), Q3PtrList< type >::count(), p, procList, qDebug(), and Q3PtrList< type >::remove().

Referenced by sigchldHnd().

00328 {
00329     procList->remove( p );
00330 #if defined(QT_Q3PROCESS_DEBUG)
00331     qDebug( "Q3ProcessManager: remove process (procList.count(): %d)", procList->count() );
00332 #endif
00333     cleanup();
00334 }

Here is the call graph for this function:

void Q3ProcessManager::cleanup (  ) 

Definition at line 336 of file q3process_unix.cpp.

References Q3PtrList< type >::count(), procList, removeMe(), QTimer::singleShot(), and SLOT.

Referenced by remove(), and Q3Process::start().

00337 {
00338     if ( procList->count() == 0 ) {
00339   QTimer::singleShot( 0, this, SLOT(removeMe()) );
00340     }
00341 }

Here is the call graph for this function:

void Q3ProcessManager::removeMe (  )  [slot]

Definition at line 343 of file q3process_unix.cpp.

References Q3PtrList< type >::count(), procList, Q3ProcessPrivate::procManager, q3process_cleanup(), and qRemovePostRoutine().

Referenced by cleanup().

00344 {
00345     if ( procList->count() == 0 ) {
00346   qRemovePostRoutine(q3process_cleanup);
00347   Q3ProcessPrivate::procManager = 0;
00348   delete this;
00349     }
00350 }

void Q3ProcessManager::sigchldHnd ( int   )  [slot]

Definition at line 352 of file q3process_unix.cpp.

References Q3Process::d, emit, Q3PtrList< type >::first(), QSocketNotifier::isEnabled(), Q3Process::isRunning(), Q3PtrList< type >::next(), Q3ProcessPrivate::notifierStderr, Q3ProcessPrivate::notifierStdout, Q3Process::notifyOnExit, QProc::pid, QProc::process, Q3Process::processExited(), procList, qDebug(), remove(), QSocketNotifier::setEnabled(), sn, Q3Process::socketRead(), QProc::socketStderr, and QProc::socketStdout.

Referenced by Q3Process::isRunning(), and Q3ProcessManager().

00353 {
00354     // Disable the socket notifier to make sure that this function is not
00355     // called recursively -- this can happen, if you enter the event loop in
00356     // the slot connected to the processExited() signal (e.g. by showing a
00357     // modal dialog) and there are more than one process which exited in the
00358     // meantime.
00359     if ( sn ) {
00360   if ( !sn->isEnabled() )
00361       return;
00362   sn->setEnabled( false );
00363     }
00364 
00365     char tmp;
00366     ::read( fd, &tmp, sizeof(tmp) );
00367 #if defined(QT_Q3PROCESS_DEBUG)
00368     qDebug( "Q3ProcessManager::sigchldHnd()" );
00369 #endif
00370     QProc *proc;
00371     Q3Process *process;
00372     bool removeProc;
00373     proc = procList->first();
00374     while ( proc != 0 ) {
00375   removeProc = false;
00376   process = proc->process;
00377   if ( process != 0 ) {
00378       if ( !process->isRunning() ) {
00379 #if defined(QT_Q3PROCESS_DEBUG)
00380     qDebug( "Q3ProcessManager::sigchldHnd() (PID: %d): process exited (Q3Process available)", proc->pid );
00381 #endif
00382     /*
00383       Apparently, there is not consistency among different
00384       operating systems on how to use FIONREAD.
00385 
00386       FreeBSD, Linux and Solaris all expect the 3rd
00387       argument to ioctl() to be an int, which is normally
00388       32-bit even on 64-bit machines.
00389 
00390       IRIX, on the other hand, expects a size_t, which is
00391       64-bit on 64-bit machines.
00392 
00393       So, the solution is to use size_t initialized to
00394       zero to make sure all bits are set to zero,
00395       preventing underflow with the FreeBSD/Linux/Solaris
00396       ioctls.
00397     */
00398     size_t nbytes = 0;
00399     // read pending data
00400     if ( proc->socketStdout && ::ioctl(proc->socketStdout, FIONREAD, (char*)&nbytes)==0 && nbytes>0 ) {
00401 #if defined(QT_Q3PROCESS_DEBUG)
00402         qDebug( "Q3ProcessManager::sigchldHnd() (PID: %d): reading %d bytes of pending data on stdout", proc->pid, nbytes );
00403 #endif
00404         process->socketRead( proc->socketStdout );
00405     }
00406     nbytes = 0;
00407     if ( proc->socketStderr && ::ioctl(proc->socketStderr, FIONREAD, (char*)&nbytes)==0 && nbytes>0 ) {
00408 #if defined(QT_Q3PROCESS_DEBUG)
00409         qDebug( "Q3ProcessManager::sigchldHnd() (PID: %d): reading %d bytes of pending data on stderr", proc->pid, nbytes );
00410 #endif
00411         process->socketRead( proc->socketStderr );
00412     }
00413     // close filedescriptors if open, and disable the
00414     // socket notifiers
00415     if ( proc->socketStdout ) {
00416         ::close( proc->socketStdout );
00417         proc->socketStdout = 0;
00418         if (process->d->notifierStdout)
00419       process->d->notifierStdout->setEnabled(false);
00420     }
00421     if ( proc->socketStderr ) {
00422         ::close( proc->socketStderr );
00423         proc->socketStderr = 0;
00424         if (process->d->notifierStderr)
00425       process->d->notifierStderr->setEnabled(false);
00426     }
00427 
00428     if ( process->notifyOnExit )
00429         emit process->processExited();
00430 
00431     removeProc = true;
00432       }
00433   } else {
00434       int status;
00435       if ( ::waitpid( proc->pid, &status, WNOHANG ) == proc->pid ) {
00436 #if defined(QT_Q3PROCESS_DEBUG)
00437     qDebug( "Q3ProcessManager::sigchldHnd() (PID: %d): process exited (Q3Process not available)", proc->pid );
00438 #endif
00439     removeProc = true;
00440       }
00441   }
00442   if ( removeProc ) {
00443       QProc *oldproc = proc;
00444       proc = procList->next();
00445       remove( oldproc );
00446   } else {
00447       proc = procList->next();
00448   }
00449     }
00450     if ( sn )
00451   sn->setEnabled( true );
00452 }


Member Data Documentation

struct sigaction Q3ProcessManager::oldactChld

Definition at line 179 of file q3process_unix.cpp.

Referenced by Q3ProcessManager(), and ~Q3ProcessManager().

struct sigaction Q3ProcessManager::oldactPipe

Definition at line 180 of file q3process_unix.cpp.

Referenced by Q3ProcessManager(), and ~Q3ProcessManager().

Q3PtrList<QProc>* Q3ProcessManager::procList

Definition at line 181 of file q3process_unix.cpp.

Referenced by append(), cleanup(), Q3ProcessPrivate::closeOpenSocketsForChild(), Q3ProcessManager(), remove(), removeMe(), sigchldHnd(), and ~Q3ProcessManager().

int Q3ProcessManager::sigchldFd[2]

Definition at line 182 of file q3process_unix.cpp.

Referenced by Q3ProcessPrivate::closeOpenSocketsForChild(), Q3Process::isRunning(), Q3ProcessManager(), qt_C_sigchldHnd(), and ~Q3ProcessManager().

QSocketNotifier* Q3ProcessManager::sn [private]

Definition at line 185 of file q3process_unix.cpp.

Referenced by Q3ProcessManager(), and sigchldHnd().


The documentation for this class was generated from the following file:
Generated on Thu Mar 15 16:13:29 2007 for Qt 4.2 User's Guide by  doxygen 1.5.1