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

tdecore

  • tdecore
kprocctrl.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 "kprocess.h"
21 #include "kprocctrl.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 
36 TDEProcessController *TDEProcessController::theTDEProcessController;
37 int TDEProcessController::refCount;
38 
39 void TDEProcessController::ref()
40 {
41  if( !refCount ) {
42  theTDEProcessController = new TDEProcessController;
43  setupHandlers();
44  }
45  refCount++;
46 }
47 
48 void TDEProcessController::deref()
49 {
50  refCount--;
51  if( !refCount ) {
52  resetHandlers();
53  delete theTDEProcessController;
54  theTDEProcessController = 0;
55  }
56 }
57 
58 TDEProcessController::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, TQT_SIGNAL(activated(int)),
75  TQT_SLOT(slotDoHousekeeping()));
76 }
77 
78 TDEProcessController::~TDEProcessController()
79 {
80  delete notifier;
81 
82  close( fd[0] );
83  close( fd[1] );
84 }
85 
86 
87 extern "C" {
88 static void theReaper( int num )
89 {
90  TDEProcessController::theSigCHLDHandler( num );
91 }
92 }
93 
94 #ifdef Q_OS_UNIX
95 struct sigaction TDEProcessController::oldChildHandlerData;
96 #endif
97 bool TDEProcessController::handlerSet = false;
98 
99 void 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 
130 void 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
147 void 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 
165 int TDEProcessController::notifierFd() const
166 {
167  return fd[0];
168 }
169 
170 void 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 
177 void
178 TDEProcessController::rescheduleCheck()
179 {
180  if( needcheck )
181  {
182  needcheck = false;
183  char dummy = 0;
184  ::write( fd[1], &dummy, 1 );
185  }
186 }
187 
188 void 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 
223 bool 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 
261 void TDEProcessController::addTDEProcess( TDEProcess* p )
262 {
263  kProcessList.append( p );
264 }
265 
266 void TDEProcessController::removeTDEProcess( TDEProcess* p )
267 {
268  kProcessList.remove( p );
269 }
270 
271 void 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 "kprocctrl.moc"
TDEProcessController
Used internally by TDEProcess.
Definition: kprocctrl.h:39
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: kprocctrl.h:60
TDEProcessController::waitForProcessExit
bool waitForProcessExit(int timeout)
Wait for any process to exit and handle their exit without starting an event loop.
Definition: kprocctrl.cpp:223
TDEProcessController::unscheduleCheck
void unscheduleCheck()
Call this function to defer processing of the data that became available on notifierFd().
Definition: kprocctrl.cpp:170
TDEProcessController::deref
static void deref()
Destroy the instance if one exists and it is not referenced any more.
Definition: kprocctrl.cpp:48
TDEProcessController::ref
static void ref()
Create an instance if none exists yet.
Definition: kprocctrl.cpp:39
TDEProcessController::theSigCHLDHandler
static void theSigCHLDHandler(int signal)
Automatically called upon SIGCHLD.
Definition: kprocctrl.cpp:147
TDEProcessController::rescheduleCheck
void rescheduleCheck()
This function must be called at some point after calling unscheduleCheck().
Definition: kprocctrl.cpp:178
TDEProcess::processHasExited
virtual void processHasExited(int state)
Immediately called after a successfully started process in NotifyOnExit mode has exited.
Definition: kprocess.cpp:821
KStdAction::close
TDEAction * close(const TQObject *recvr, const char *slot, TDEActionCollection *parent, const char *name=0)
TDEProcess
Child process invocation, monitoring and control.
Definition: kprocess.h:130
TDEProcess::runs
bool runs
true if the process is currently running.
Definition: kprocess.h:708
TDEProcess::pid_
pid_t pid_
The PID of the currently running process.
Definition: kprocess.h:717

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
  •     tdecore
  • tdeabc
  • tdecmshell
  • tdecore
  • tdefx
  • tdehtml
  • tdeinit
  • tdeio
  •   bookmarks
  •   httpfilter
  •   kpasswdserver
  •   kssl
  • tdeioslave
  •   http
  •   tdefile
  •   tdeio
  •   tdeioexec
  • tdemdi
  •   tdemdi
  • tdenewstuff
  • tdeparts
  • tdeprint
  • tderandr
  • tderesources
  • tdespell2
  • tdesu
  • tdeui
  • tdeunittest
  • tdeutils
  • tdewallet
Generated for tdecore by doxygen 1.8.8
This website is maintained by Timothy Pearson.