• Skip to content
  • Skip to link menu
Trinity API Reference
  • Trinity API Reference
  • tdecore
 

tdecore

  • tdecore
tdeprocctrl.cpp
1/* This file is part of the KDE libraries
2 Copyright (C) 1997 Christian Czezakte (e9025461@student.tuwien.ac.at)
3
4 This library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Library General Public
6 License as published by the Free Software Foundation; either
7 version 2 of the License, or (at your option) any later version.
8
9 This library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 Library General Public License for more details.
13
14 You should have received a copy of the GNU Library General Public License
15 along with this library; see the file COPYING.LIB. If not, write to
16 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17 Boston, MA 02110-1301, USA.
18*/
19
20#include "tdeprocess.h"
21#include "tdeprocctrl.h"
22
23#include <config.h>
24
25#include <sys/time.h>
26#include <sys/types.h>
27#include <sys/wait.h>
28#include <unistd.h>
29#include <errno.h>
30#include <fcntl.h>
31#include <stdio.h>
32#include <stdlib.h>
33
34#include <tqsocketnotifier.h>
35
36TDEProcessController *TDEProcessController::theTDEProcessController;
37int TDEProcessController::refCount;
38
39void TDEProcessController::ref()
40{
41 if( !refCount ) {
42 theTDEProcessController = new TDEProcessController;
43 setupHandlers();
44 }
45 refCount++;
46}
47
48void TDEProcessController::deref()
49{
50 refCount--;
51 if( !refCount ) {
52 resetHandlers();
53 delete theTDEProcessController;
54 theTDEProcessController = 0;
55 }
56}
57
58TDEProcessController::TDEProcessController()
59 : needcheck( false )
60{
61 if( pipe( fd ) )
62 {
63 perror( "pipe" );
64 abort();
65 }
66
67 fcntl( fd[0], F_SETFL, O_NONBLOCK ); // in case slotDoHousekeeping is called without polling first
68 fcntl( fd[1], F_SETFL, O_NONBLOCK ); // in case it fills up
69 fcntl( fd[0], F_SETFD, FD_CLOEXEC );
70 fcntl( fd[1], F_SETFD, FD_CLOEXEC );
71
72 notifier = new TQSocketNotifier( fd[0], TQSocketNotifier::Read );
73 notifier->setEnabled( true );
74 TQObject::connect( notifier, TQ_SIGNAL(activated(int)),
75 TQ_SLOT(slotDoHousekeeping()));
76}
77
78TDEProcessController::~TDEProcessController()
79{
80 delete notifier;
81
82 close( fd[0] );
83 close( fd[1] );
84}
85
86
87extern "C" {
88static void theReaper( int num )
89{
90 TDEProcessController::theSigCHLDHandler( num );
91}
92}
93
94#ifdef Q_OS_UNIX
95struct sigaction TDEProcessController::oldChildHandlerData;
96#endif
97bool TDEProcessController::handlerSet = false;
98
99void TDEProcessController::setupHandlers()
100{
101 if( handlerSet )
102 return;
103 handlerSet = true;
104
105#ifdef Q_OS_UNIX
106 struct sigaction act;
107 sigemptyset( &act.sa_mask );
108
109 act.sa_handler = SIG_IGN;
110 act.sa_flags = 0;
111 sigaction( SIGPIPE, &act, 0L );
112
113 act.sa_handler = theReaper;
114 act.sa_flags = SA_NOCLDSTOP;
115 // CC: take care of SunOS which automatically restarts interrupted system
116 // calls (and thus does not have SA_RESTART)
117#ifdef SA_RESTART
118 act.sa_flags |= SA_RESTART;
119#endif
120 sigaction( SIGCHLD, &act, &oldChildHandlerData );
121
122 sigaddset( &act.sa_mask, SIGCHLD );
123 // Make sure we don't block this signal. gdb tends to do that :-(
124 sigprocmask( SIG_UNBLOCK, &act.sa_mask, 0 );
125#else
126 //TODO: win32
127#endif
128}
129
130void TDEProcessController::resetHandlers()
131{
132 if( !handlerSet )
133 return;
134 handlerSet = false;
135
136#ifdef Q_OS_UNIX
137 sigaction( SIGCHLD, &oldChildHandlerData, 0 );
138#else
139 //TODO: win32
140#endif
141 // there should be no problem with SIGPIPE staying SIG_IGN
142}
143
144// the pipe is needed to sync the child reaping with our event processing,
145// as otherwise there are race conditions, locking requirements, and things
146// generally get harder
147void TDEProcessController::theSigCHLDHandler( int arg )
148{
149 int saved_errno = errno;
150
151 char dummy = 0;
152 ::write( theTDEProcessController->fd[1], &dummy, 1 );
153
154#ifdef Q_OS_UNIX
155 if( oldChildHandlerData.sa_handler != SIG_IGN &&
156 oldChildHandlerData.sa_handler != SIG_DFL )
157 oldChildHandlerData.sa_handler( arg ); // call the old handler
158#else
159 //TODO: win32
160#endif
161
162 errno = saved_errno;
163}
164
165int TDEProcessController::notifierFd() const
166{
167 return fd[0];
168}
169
170void TDEProcessController::unscheduleCheck()
171{
172 char dummy[16]; // somewhat bigger - just in case several have queued up
173 if( ::read( fd[0], dummy, sizeof(dummy) ) > 0 )
174 needcheck = true;
175}
176
177void
178TDEProcessController::rescheduleCheck()
179{
180 if( needcheck )
181 {
182 needcheck = false;
183 char dummy = 0;
184 ::write( fd[1], &dummy, 1 );
185 }
186}
187
188void TDEProcessController::slotDoHousekeeping()
189{
190 char dummy[16]; // somewhat bigger - just in case several have queued up
191 ::read( fd[0], dummy, sizeof(dummy) );
192
193 int status;
194 again:
195 TQValueListIterator<TDEProcess*> it( kProcessList.begin() );
196 TQValueListIterator<TDEProcess*> eit( kProcessList.end() );
197 while( it != eit )
198 {
199 TDEProcess *prc = *it;
200 if( prc->runs && waitpid( prc->pid_, &status, WNOHANG ) > 0 )
201 {
202 prc->processHasExited( status );
203 // the callback can nuke the whole process list and even 'this'
204 if (!theTDEProcessController)
205 return;
206 goto again;
207 }
208 ++it;
209 }
210 TQValueListIterator<int> uit( unixProcessList.begin() );
211 TQValueListIterator<int> ueit( unixProcessList.end() );
212 while( uit != ueit )
213 {
214 if( waitpid( *uit, 0, WNOHANG ) > 0 )
215 {
216 uit = unixProcessList.remove( uit );
217 deref(); // counterpart to addProcess, can invalidate 'this'
218 } else
219 ++uit;
220 }
221}
222
223bool TDEProcessController::waitForProcessExit( int timeout )
224{
225#ifdef Q_OS_UNIX
226 for(;;)
227 {
228 struct timeval tv, *tvp;
229 if (timeout < 0)
230 tvp = 0;
231 else
232 {
233 tv.tv_sec = timeout;
234 tv.tv_usec = 0;
235 tvp = &tv;
236 }
237
238 fd_set fds;
239 FD_ZERO( &fds );
240 FD_SET( fd[0], &fds );
241
242 switch( select( fd[0]+1, &fds, 0, 0, tvp ) )
243 {
244 case -1:
245 if( errno == EINTR )
246 continue;
247 // fall through; should never happen
248 case 0:
249 return false;
250 default:
251 slotDoHousekeeping();
252 return true;
253 }
254 }
255#else
256 //TODO: win32
257 return false;
258#endif
259}
260
261void TDEProcessController::addTDEProcess( TDEProcess* p )
262{
263 kProcessList.append( p );
264}
265
266void TDEProcessController::removeTDEProcess( TDEProcess* p )
267{
268 kProcessList.remove( p );
269}
270
271void TDEProcessController::addProcess( int pid )
272{
273 unixProcessList.append( pid );
274 ref(); // make sure we stay around when the TDEProcess goes away
275}
276
277#include "tdeprocctrl.moc"
TDEProcessController
Used internally by TDEProcess.
Definition: tdeprocctrl.h:40
TDEProcessController::theSigCHLDHandler
static void theSigCHLDHandler(int signal)
Automatically called upon SIGCHLD.
Definition: tdeprocctrl.cpp:147
TDEProcessController::deref
static void deref()
Destroy the instance if one exists and it is not referenced any more.
Definition: tdeprocctrl.cpp:48
TDEProcessController::ref
static void ref()
Create an instance if none exists yet.
Definition: tdeprocctrl.cpp:39
TDEProcessController::waitForProcessExit
bool waitForProcessExit(int timeout)
Wait for any process to exit and handle their exit without starting an event loop.
Definition: tdeprocctrl.cpp:223
TDEProcessController::rescheduleCheck
void rescheduleCheck()
This function must be called at some point after calling unscheduleCheck().
Definition: tdeprocctrl.cpp:178
TDEProcessController::theTDEProcessController
static TDEProcessController * theTDEProcessController
Only a single instance of this class is allowed at a time, and this static variable is used to track ...
Definition: tdeprocctrl.h:60
TDEProcessController::unscheduleCheck
void unscheduleCheck()
Call this function to defer processing of the data that became available on notifierFd().
Definition: tdeprocctrl.cpp:170
TDEProcess
Child process invocation, monitoring and control.
Definition: tdeprocess.h:131
TDEProcess::pid_
pid_t pid_
The PID of the currently running process.
Definition: tdeprocess.h:717
TDEProcess::processHasExited
virtual void processHasExited(int state)
Immediately called after a successfully started process in NotifyOnExit mode has exited.
Definition: tdeprocess.cpp:816
TDEProcess::runs
bool runs
true if the process is currently running.
Definition: tdeprocess.h:708
KStdAction::close
TDEAction * close(const TQObject *recvr, const char *slot, TDEActionCollection *parent, const char *name=0)

tdecore

Skip menu "tdecore"
  • Main Page
  • Modules
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members
  • Related Pages

tdecore

Skip menu "tdecore"
  • arts
  • dcop
  • dnssd
  • interfaces
  •   kspeech
  •     interface
  •     library
  •   tdetexteditor
  • kate
  • kded
  • kdoctools
  • kimgio
  • kjs
  • libtdemid
  • libtdescreensaver
  • tdeabc
  • tdecmshell
  • tdecore
  • tdefx
  • tdehtml
  • tdeinit
  • tdeio
  •   bookmarks
  •   httpfilter
  •   kpasswdserver
  •   kssl
  •   tdefile
  •   tdeio
  •   tdeioexec
  • tdeioslave
  •   http
  • tdemdi
  •   tdemdi
  • tdenewstuff
  • tdeparts
  • tdeprint
  • tderandr
  • tderesources
  • tdespell2
  • tdesu
  • tdeui
  • tdeunittest
  • tdeutils
  • tdewallet
Generated for tdecore by doxygen 1.9.4
This website is maintained by Timothy Pearson.