27 #include <QtCore/QMap>
28 #include <QtCore/QFile>
29 #include <QtCore/QSocketNotifier>
38 int KfsProcessController::s_refCount = 0;
40 void KfsProcessController::ref()
49 void KfsProcessController::deref()
64 KfsProcessController::KfsProcessController()
72 fcntl( m_fd[0], F_SETFL, O_NONBLOCK );
73 fcntl( m_fd[1], F_SETFL, O_NONBLOCK );
74 fcntl( m_fd[0], F_SETFD, FD_CLOEXEC );
75 fcntl( m_fd[1], F_SETFD, FD_CLOEXEC );
77 m_notifier =
new QSocketNotifier( m_fd[0], QSocketNotifier::Read );
78 m_notifier->setEnabled(
true );
79 QObject::connect( m_notifier, SIGNAL(activated(
int)),
80 SLOT(slotDoHousekeeping()));
83 KfsProcessController::~KfsProcessController()
90 #warning FIXME: why does close() freeze up destruction?
103 bool KfsProcessController::s_handlerSet = false;
105 void KfsProcessController::setupHandlers()
111 struct sigaction act;
112 sigemptyset( &act.sa_mask );
114 act.sa_handler = SIG_IGN;
116 sigaction( SIGPIPE, &act, 0L );
119 act.sa_flags = SA_NOCLDSTOP;
123 act.sa_flags |= SA_RESTART;
125 sigaction( SIGCHLD, &act, &s_oldChildHandlerData );
127 sigaddset( &act.sa_mask, SIGCHLD );
129 sigprocmask( SIG_UNBLOCK, &act.sa_mask, 0 );
132 void KfsProcessController::resetHandlers()
136 s_handlerSet =
false;
138 sigset_t
mask, omask;
139 sigemptyset( &mask );
140 sigaddset( &mask, SIGCHLD );
141 sigprocmask( SIG_BLOCK, &mask, &omask );
143 struct sigaction act;
144 sigaction( SIGCHLD, &s_oldChildHandlerData, &act );
146 sigaction( SIGCHLD, &act, 0 );
150 sigprocmask( SIG_SETMASK, &omask, 0 );
159 int saved_errno = errno;
162 ::write( instance()->m_fd[1], &dummy, 1 );
164 if ( s_oldChildHandlerData.sa_handler != SIG_IGN &&
165 s_oldChildHandlerData.sa_handler != SIG_DFL ) {
166 s_oldChildHandlerData.sa_handler( arg );
172 void KfsProcessController::slotDoHousekeeping()
175 ::read( m_fd[0], dummy,
sizeof(dummy) );
183 if( prc->runs && waitpid( prc->pid_, 0, WNOHANG ) > 0 )
185 prc->processHasExited();
197 if( waitpid( *uit, 0, WNOHANG ) > 0 )
199 uit = m_unixProcessList.erase( uit );
206 void KfsProcessController::addKProcess(
KfsProcess* p )
208 m_kProcessList.append( p );
211 void KfsProcessController::removeKProcess(
KfsProcess* p )
213 m_kProcessList.removeAll( p );
216 void KfsProcessController::addProcess(
int pid )
218 m_unixProcessList.append( pid );
231 KfsProcessController::ref();
232 KfsProcessController::instance()->addKProcess(
this);
237 KfsProcessController::instance()->removeKProcess(
this);
238 KfsProcessController::deref();
244 KfsProcessController::instance()->addProcess(pid_);
252 arguments.append(QByteArray(arg));
258 arguments.append(QFile::encodeName(arg));
265 kDebug(175) <<
"Attempted to start an already running process";
269 uint n = arguments.count();
271 kDebug(175) <<
"Attempted to start a process without arguments";
274 char **arglist =
static_cast<char **
>(malloc( (n + 1) *
sizeof(
char *)));
275 for (uint i = 0; i < n; i++)
276 arglist[i] = arguments[i].data();
289 fcntl(fd[1], F_SETFD, FD_CLOEXEC);
292 struct sigaction act;
293 sigemptyset(&act.sa_mask);
294 act.sa_handler = SIG_DFL;
296 for (
int sig = 1; sig < NSIG; sig++)
297 sigaction(sig, &act, 0L);
300 execvp(arglist[0], arglist);
303 write(fd[1], &resultByte, 1);
305 }
else if (pid_ == -1) {
320 int n = ::read(fd[0], &resultByte, 1);
342 void KfsProcess::processHasExited()
349 #include "kfsprocess.moc"
QDebug perror(QDebug s, KDebugTag)
static QDebug kDebug(bool cond, int area=KDE_DEFAULT_DEBUG_AREA)
static void theReaper(int num)
KfsProcess & operator<<(const QString &arg)
KfsProcess(QObject *parent=0L)
static void theSigCHLDHandler(int signal)
KAction * close(const QObject *recvr, const char *slot, QObject *parent)