26 #include <sys/types.h> 34 #include <QtCore/QSocketNotifier> 36 class K3ProcessController::Private
52 QSocketNotifier *notifier;
55 static struct sigaction oldChildHandlerData;
56 static bool handlerSet;
62 int K3ProcessController::Private::refCount = 0;
66 if ( !Private::refCount ) {
76 if( !Private::refCount ) {
78 delete Private::instance;
79 Private::instance = 0;
92 return Private::instance;
95 K3ProcessController::K3ProcessController()
104 fcntl( d->fd[0], F_SETFL, O_NONBLOCK );
105 fcntl( d->fd[1], F_SETFL, O_NONBLOCK );
106 fcntl( d->fd[0], F_SETFD, FD_CLOEXEC );
107 fcntl( d->fd[1], F_SETFD, FD_CLOEXEC );
109 d->notifier =
new QSocketNotifier( d->fd[0], QSocketNotifier::Read );
110 d->notifier->setEnabled(
true );
111 QObject::connect( d->notifier, SIGNAL(activated(
int)),
112 SLOT(slotDoHousekeeping()));
115 K3ProcessController::~K3ProcessController()
122 #warning FIXME: why does close() freeze up destruction? 139 bool K3ProcessController::Private::handlerSet = false;
141 void K3ProcessController::setupHandlers()
143 if( Private::handlerSet )
145 Private::handlerSet =
true;
148 struct sigaction act;
149 sigemptyset( &act.sa_mask );
151 act.sa_handler = SIG_IGN;
153 sigaction( SIGPIPE, &act, 0L );
156 act.sa_flags = SA_NOCLDSTOP;
160 act.sa_flags |= SA_RESTART;
162 sigaction( SIGCHLD, &act, &Private::oldChildHandlerData );
164 sigaddset( &act.sa_mask, SIGCHLD );
166 sigprocmask( SIG_UNBLOCK, &act.sa_mask, 0 );
172 void K3ProcessController::resetHandlers()
174 if( !Private::handlerSet )
176 Private::handlerSet =
false;
179 sigset_t
mask, omask;
180 sigemptyset( &mask );
181 sigaddset( &mask, SIGCHLD );
182 sigprocmask( SIG_BLOCK, &mask, &omask );
184 struct sigaction act;
185 sigaction( SIGCHLD, &Private::oldChildHandlerData, &act );
187 sigaction( SIGCHLD, &act, 0 );
188 Private::handlerSet =
true;
191 sigprocmask( SIG_SETMASK, &omask, 0 );
203 int saved_errno = errno;
206 ::write(
instance()->d->fd[1], &dummy, 1 );
209 if ( Private::oldChildHandlerData.sa_handler != SIG_IGN &&
210 Private::oldChildHandlerData.sa_handler != SIG_DFL ) {
211 Private::oldChildHandlerData.sa_handler( arg );
228 if( ::read( d->fd[0], dummy,
sizeof(dummy) ) > 0 )
237 d->needcheck =
false;
239 ::write( d->fd[1], &dummy, 1 );
243 void K3ProcessController::slotDoHousekeeping()
246 ::read( d->fd[0], dummy,
sizeof(dummy) );
255 if( prc->
runs && waitpid( prc->
pid_, &status, WNOHANG ) > 0 )
269 if( waitpid( *uit, 0, WNOHANG ) > 0 )
271 uit = d->unixProcessList.erase( uit );
283 struct timeval tv, *tvp;
295 FD_SET( d->fd[0], &fds );
297 switch( select( d->fd[0]+1, &fds, 0, 0, tvp ) )
306 slotDoHousekeeping();
318 d->kProcessList.append( p );
323 d->kProcessList.removeAll( p );
328 d->unixProcessList.append( pid );
332 #include "k3processcontroller.moc" virtual void processHasExited(int state)
Immediately called after a successfully started process in NotifyOnExit mode has exited.
static void theReaper(int num)
QDebug perror(QDebug s, KDebugTag)
bool waitForProcessExit(int timeout)
Wait for any process to exit and handle their exit without starting an event loop.
void removeKProcess(K3Process *)
Used internally by K3Process.
static void deref()
Destroy the instance if one exists and it is not referenced any more.
static void ref()
Create an instance if none exists yet.
void rescheduleCheck()
This function must be called at some point after calling unscheduleCheck().
void unscheduleCheck()
Call this function to defer processing of the data that became available on notifierFd().
void addKProcess(K3Process *)
pid_t pid_
The PID of the currently running process.
static void theSigCHLDHandler(int signal)
Automatically called upon SIGCHLD.
static K3ProcessController * instance()
Only a single instance of this class is allowed at a time.
bool runs
true if the process is currently running.
KAction * close(const QObject *recvr, const char *slot, QObject *parent)