-rw-r--r-- | libopie/oprocctrl.cpp | 1 |
1 files changed, 0 insertions, 1 deletions
diff --git a/libopie/oprocctrl.cpp b/libopie/oprocctrl.cpp index e7db622..df8da1e 100644 --- a/libopie/oprocctrl.cpp +++ b/libopie/oprocctrl.cpp @@ -1,170 +1,169 @@ /* This file is part of the KDE libraries Copyright (C) 1997 Christian Czezakte (e9025461@student.tuwien.ac.at) This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ // // KPROCESSCONTROLLER -- A helper class for KProcess // // version 0.3.1, Jan, 8th 1997 // // (C) Christian Czezatke // e9025461@student.tuwien.ac.at // Ported by Holger Freyther // //#include <config.h> #include <sys/types.h> #include <sys/socket.h> #include <errno.h> #include <fcntl.h> #include <stdio.h> #include <string.h> #include <unistd.h> #include <assert.h> #include <qsocketnotifier.h> -#include "oprocess.h" #include "oprocctrl.h" OProcessController *OProcessController::theOProcessController = 0; struct sigaction OProcessController::oldChildHandlerData; bool OProcessController::handlerSet = false; OProcessController::OProcessController() { assert( theOProcessController == 0 ); if (0 > pipe(fd)) printf(strerror(errno)); notifier = new QSocketNotifier(fd[0], QSocketNotifier::Read); notifier->setEnabled(true); QObject::connect(notifier, SIGNAL(activated(int)), this, SLOT(slotDoHousekeeping(int))); connect( &delayedChildrenCleanupTimer, SIGNAL( timeout()), SLOT( delayedChildrenCleanup())); theOProcessController = this; setupHandlers(); } void OProcessController::setupHandlers() { if( handlerSet ) return; struct sigaction act; act.sa_handler=theSigCHLDHandler; sigemptyset(&(act.sa_mask)); sigaddset(&(act.sa_mask), SIGCHLD); // Make sure we don't block this signal. gdb tends to do that :-( sigprocmask(SIG_UNBLOCK, &(act.sa_mask), 0); act.sa_flags = SA_NOCLDSTOP; // CC: take care of SunOS which automatically restarts interrupted system // calls (and thus does not have SA_RESTART) #ifdef SA_RESTART act.sa_flags |= SA_RESTART; #endif sigaction( SIGCHLD, &act, &oldChildHandlerData ); act.sa_handler=SIG_IGN; sigemptyset(&(act.sa_mask)); sigaddset(&(act.sa_mask), SIGPIPE); act.sa_flags = 0; sigaction( SIGPIPE, &act, 0L); handlerSet = true; } void OProcessController::resetHandlers() { if( !handlerSet ) return; sigaction( SIGCHLD, &oldChildHandlerData, 0 ); // there should be no problem with SIGPIPE staying SIG_IGN handlerSet = false; } // block SIGCHLD handler, because it accesses processList void OProcessController::addOProcess( OProcess* p ) { sigset_t newset, oldset; sigemptyset( &newset ); sigaddset( &newset, SIGCHLD ); sigprocmask( SIG_BLOCK, &newset, &oldset ); processList.append( p ); sigprocmask( SIG_SETMASK, &oldset, 0 ); } void OProcessController::removeOProcess( OProcess* p ) { sigset_t newset, oldset; sigemptyset( &newset ); sigaddset( &newset, SIGCHLD ); sigprocmask( SIG_BLOCK, &newset, &oldset ); processList.remove( p ); sigprocmask( SIG_SETMASK, &oldset, 0 ); } //using a struct which contains both the pid and the status makes it easier to write //and read the data into the pipe //especially this solves a problem which appeared on my box where slotDoHouseKeeping() received //only 4 bytes (with some debug output around the write()'s it received all 8 bytes) //don't know why this happened, but when writing all 8 bytes at once it works here, aleXXX struct waitdata { pid_t pid; int status; }; void OProcessController::theSigCHLDHandler(int arg) { struct waitdata wd; // int status; // pid_t this_pid; int saved_errno; saved_errno = errno; // since waitpid and write change errno, we have to save it and restore it // (Richard Stevens, Advanced programming in the Unix Environment) bool found = false; if( theOProcessController != 0 ) { // iterating the list doesn't perform any system call for( QValueList<OProcess*>::ConstIterator it = theOProcessController->processList.begin(); it != theOProcessController->processList.end(); ++it ) { if( !(*it)->isRunning()) continue; wd.pid = waitpid( (*it)->pid(), &wd.status, WNOHANG ); if ( wd.pid > 0 ) { ::write(theOProcessController->fd[1], &wd, sizeof(wd)); found = true; } } } if( !found && oldChildHandlerData.sa_handler != SIG_IGN && oldChildHandlerData.sa_handler != SIG_DFL ) oldChildHandlerData.sa_handler( arg ); // call the old handler |