Diffstat (limited to 'core/launcher/qprocess_unix.cpp') (more/less context) (show whitespace changes)
-rw-r--r-- | core/launcher/qprocess_unix.cpp | 93 |
1 files changed, 46 insertions, 47 deletions
diff --git a/core/launcher/qprocess_unix.cpp b/core/launcher/qprocess_unix.cpp index 19a8c93..d62e4e6 100644 --- a/core/launcher/qprocess_unix.cpp +++ b/core/launcher/qprocess_unix.cpp | |||
@@ -9,60 +9,59 @@ | |||
9 | ** packaging of this file. | 9 | ** packaging of this file. |
10 | ** | 10 | ** |
11 | ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE | 11 | ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE |
12 | ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. | 12 | ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. |
13 | ** | 13 | ** |
14 | ** See http://www.trolltech.com/gpl/ for GPL licensing information. | 14 | ** See http://www.trolltech.com/gpl/ for GPL licensing information. |
15 | ** | 15 | ** |
16 | ** Contact info@trolltech.com if any conditions of this licensing are | 16 | ** Contact info@trolltech.com if any conditions of this licensing are |
17 | ** not clear to you. | 17 | ** not clear to you. |
18 | ** | 18 | ** |
19 | **********************************************************************/ | 19 | **********************************************************************/ |
20 | 20 | ||
21 | //#include "qplatformdefs.h" | ||
22 | |||
23 | // Solaris redefines connect -> __xnet_connect with _XOPEN_SOURCE_EXTENDED. | 21 | // Solaris redefines connect -> __xnet_connect with _XOPEN_SOURCE_EXTENDED. |
24 | #if defined(connect) | 22 | #if defined(connect) |
25 | #undef connect | 23 | #undef connect |
26 | #endif | 24 | #endif |
27 | 25 | ||
28 | #include "qprocess.h" | 26 | #include "qprocess.h" |
29 | 27 | ||
30 | #ifndef QT_NO_PROCESS | 28 | /* OPIE */ |
29 | #include <opie2/odebug.h> | ||
30 | using namespace Opie::Core; | ||
31 | 31 | ||
32 | #include "qapplication.h" | 32 | /* QT */ |
33 | #include "qqueue.h" | 33 | #ifndef QT_NO_PROCESS |
34 | #include "qlist.h" | 34 | #include <qapplication.h> |
35 | #include "qsocketnotifier.h" | 35 | #include <qqueue.h> |
36 | #include "qtimer.h" | 36 | #include <qlist.h> |
37 | #include "qregexp.h" | 37 | #include <qsocketnotifier.h> |
38 | #include <qtimer.h> | ||
39 | #include <qregexp.h> | ||
38 | 40 | ||
39 | #include "qcleanuphandler_p.h" | 41 | #include "qcleanuphandler_p.h" |
40 | 42 | ||
43 | /* STD */ | ||
41 | #include <stdlib.h> | 44 | #include <stdlib.h> |
42 | |||
43 | // ### FOR Qt 2.3 compat | ||
44 | #include <unistd.h> | 45 | #include <unistd.h> |
45 | #include <signal.h> | 46 | #include <signal.h> |
46 | #include <sys/socket.h> | 47 | #include <sys/socket.h> |
47 | #include <sys/ioctl.h> | 48 | #include <sys/ioctl.h> |
48 | #include <sys/wait.h> | 49 | #include <sys/wait.h> |
49 | #include <sys/fcntl.h> | 50 | #include <sys/fcntl.h> |
50 | 51 | #include <sys/resource.h> | |
51 | #include <errno.h> | 52 | #include <errno.h> |
52 | |||
53 | #ifdef Q_OS_MACX | 53 | #ifdef Q_OS_MACX |
54 | #include <sys/time.h> | 54 | #include <sys/time.h> |
55 | #endif | 55 | #endif |
56 | #include <sys/resource.h> | ||
57 | 56 | ||
58 | #ifdef __MIPSEL__ | 57 | #ifdef __MIPSEL__ |
59 | # ifndef SOCK_DGRAM | 58 | # ifndef SOCK_DGRAM |
60 | # define SOCK_DGRAM 1 | 59 | # define SOCK_DGRAM 1 |
61 | # endif | 60 | # endif |
62 | # ifndef SOCK_STREAM | 61 | # ifndef SOCK_STREAM |
63 | # define SOCK_STREAM 2 | 62 | # define SOCK_STREAM 2 |
64 | # endif | 63 | # endif |
65 | #endif | 64 | #endif |
66 | 65 | ||
67 | //#define QT_QPROCESS_DEBUG | 66 | //#define QT_QPROCESS_DEBUG |
68 | 67 | ||
@@ -123,34 +122,34 @@ public: | |||
123 | child processes: if the process is finished, the QProcess class may still be | 122 | child processes: if the process is finished, the QProcess class may still be |
124 | there; furthermore a user can use QProcess to start more than one process. | 123 | there; furthermore a user can use QProcess to start more than one process. |
125 | 124 | ||
126 | The helper-class QProc has the semantics that one instance of this class maps | 125 | The helper-class QProc has the semantics that one instance of this class maps |
127 | directly to a running child process. | 126 | directly to a running child process. |
128 | */ | 127 | */ |
129 | class QProc | 128 | class QProc |
130 | { | 129 | { |
131 | public: | 130 | public: |
132 | QProc( pid_t p, QProcess *proc=0 ) : pid(p), process(proc) | 131 | QProc( pid_t p, QProcess *proc=0 ) : pid(p), process(proc) |
133 | { | 132 | { |
134 | #if defined(QT_QPROCESS_DEBUG) | 133 | #if defined(QT_QPROCESS_DEBUG) |
135 | qDebug( "QProc: Constructor for pid %d and QProcess %p", pid, process ); | 134 | odebug << "QProc: Constructor for pid " << pid << " and QProcess " << process << "" << oendl; |
136 | #endif | 135 | #endif |
137 | socketStdin = 0; | 136 | socketStdin = 0; |
138 | socketStdout = 0; | 137 | socketStdout = 0; |
139 | socketStderr = 0; | 138 | socketStderr = 0; |
140 | } | 139 | } |
141 | ~QProc() | 140 | ~QProc() |
142 | { | 141 | { |
143 | #if defined(QT_QPROCESS_DEBUG) | 142 | #if defined(QT_QPROCESS_DEBUG) |
144 | qDebug( "QProc: Destructor for pid %d and QProcess %p", pid, process ); | 143 | odebug << "QProc: Destructor for pid " << pid << " and QProcess " << process << "" << oendl; |
145 | #endif | 144 | #endif |
146 | if ( process != 0 ) { | 145 | if ( process != 0 ) { |
147 | if ( process->d->notifierStdin ) | 146 | if ( process->d->notifierStdin ) |
148 | process->d->notifierStdin->setEnabled( FALSE ); | 147 | process->d->notifierStdin->setEnabled( FALSE ); |
149 | if ( process->d->notifierStdout ) | 148 | if ( process->d->notifierStdout ) |
150 | process->d->notifierStdout->setEnabled( FALSE ); | 149 | process->d->notifierStdout->setEnabled( FALSE ); |
151 | if ( process->d->notifierStderr ) | 150 | if ( process->d->notifierStderr ) |
152 | process->d->notifierStderr->setEnabled( FALSE ); | 151 | process->d->notifierStderr->setEnabled( FALSE ); |
153 | process->d->proc = 0; | 152 | process->d->proc = 0; |
154 | } | 153 | } |
155 | if( socketStdin != 0 ) | 154 | if( socketStdin != 0 ) |
156 | ::close( socketStdin ); | 155 | ::close( socketStdin ); |
@@ -204,102 +203,102 @@ QProcessManager::QProcessManager() | |||
204 | { | 203 | { |
205 | procList = new QList<QProc>; | 204 | procList = new QList<QProc>; |
206 | procList->setAutoDelete( TRUE ); | 205 | procList->setAutoDelete( TRUE ); |
207 | 206 | ||
208 | // The SIGCHLD handler writes to a socket to tell the manager that | 207 | // The SIGCHLD handler writes to a socket to tell the manager that |
209 | // something happened. This is done to get the processing in sync with the | 208 | // something happened. This is done to get the processing in sync with the |
210 | // event reporting. | 209 | // event reporting. |
211 | if ( ::socketpair( AF_UNIX, SOCK_STREAM, 0, sigchldFd ) ) { | 210 | if ( ::socketpair( AF_UNIX, SOCK_STREAM, 0, sigchldFd ) ) { |
212 | sigchldFd[0] = 0; | 211 | sigchldFd[0] = 0; |
213 | sigchldFd[1] = 0; | 212 | sigchldFd[1] = 0; |
214 | } else { | 213 | } else { |
215 | #if defined(QT_QPROCESS_DEBUG) | 214 | #if defined(QT_QPROCESS_DEBUG) |
216 | qDebug( "QProcessManager: install socket notifier (%d)", sigchldFd[1] ); | 215 | odebug << "QProcessManager: install socket notifier (" << sigchldFd[1] << ")" << oendl; |
217 | #endif | 216 | #endif |
218 | QSocketNotifier *sn = new QSocketNotifier( sigchldFd[1], | 217 | QSocketNotifier *sn = new QSocketNotifier( sigchldFd[1], |
219 | QSocketNotifier::Read, this ); | 218 | QSocketNotifier::Read, this ); |
220 | connect( sn, SIGNAL(activated(int)), | 219 | connect( sn, SIGNAL(activated(int)), |
221 | this, SLOT(sigchldHnd(int)) ); | 220 | this, SLOT(sigchldHnd(int)) ); |
222 | sn->setEnabled( TRUE ); | 221 | sn->setEnabled( TRUE ); |
223 | } | 222 | } |
224 | 223 | ||
225 | // install a SIGCHLD handler and ignore SIGPIPE | 224 | // install a SIGCHLD handler and ignore SIGPIPE |
226 | struct sigaction act; | 225 | struct sigaction act; |
227 | 226 | ||
228 | #if defined(QT_QPROCESS_DEBUG) | 227 | #if defined(QT_QPROCESS_DEBUG) |
229 | qDebug( "QProcessManager: install a SIGCHLD handler" ); | 228 | odebug << "QProcessManager: install a SIGCHLD handler" << oendl; |
230 | #endif | 229 | #endif |
231 | act.sa_handler = qt_C_sigchldHnd; | 230 | act.sa_handler = qt_C_sigchldHnd; |
232 | sigemptyset( &(act.sa_mask) ); | 231 | sigemptyset( &(act.sa_mask) ); |
233 | sigaddset( &(act.sa_mask), SIGCHLD ); | 232 | sigaddset( &(act.sa_mask), SIGCHLD ); |
234 | act.sa_flags = SA_NOCLDSTOP; | 233 | act.sa_flags = SA_NOCLDSTOP; |
235 | #if defined(SA_RESTART) | 234 | #if defined(SA_RESTART) |
236 | act.sa_flags |= SA_RESTART; | 235 | act.sa_flags |= SA_RESTART; |
237 | #endif | 236 | #endif |
238 | if ( sigaction( SIGCHLD, &act, &oldactChld ) != 0 ) | 237 | if ( sigaction( SIGCHLD, &act, &oldactChld ) != 0 ) |
239 | qWarning( "Error installing SIGCHLD handler" ); | 238 | owarn << "Error installing SIGCHLD handler" << oendl; |
240 | 239 | ||
241 | #if defined(QT_QPROCESS_DEBUG) | 240 | #if defined(QT_QPROCESS_DEBUG) |
242 | qDebug( "QProcessManager: install a SIGPIPE handler (SIG_IGN)" ); | 241 | odebug << "QProcessManager: install a SIGPIPE handler (SIG_IGN)" << oendl; |
243 | #endif | 242 | #endif |
244 | /* | 243 | /* |
245 | Using qt_C_sigpipeHnd rather than SIG_IGN is a workaround | 244 | Using qt_C_sigpipeHnd rather than SIG_IGN is a workaround |
246 | for a strange problem where GNU tar (called by backuprestore) | 245 | for a strange problem where GNU tar (called by backuprestore) |
247 | would hang on filesystem-full. Strangely, the qt_C_sigpipeHnd | 246 | would hang on filesystem-full. Strangely, the qt_C_sigpipeHnd |
248 | is never even called, yet this avoids the hang. | 247 | is never even called, yet this avoids the hang. |
249 | */ | 248 | */ |
250 | act.sa_handler = qt_C_sigpipeHnd; | 249 | act.sa_handler = qt_C_sigpipeHnd; |
251 | sigemptyset( &(act.sa_mask) ); | 250 | sigemptyset( &(act.sa_mask) ); |
252 | sigaddset( &(act.sa_mask), SIGPIPE ); | 251 | sigaddset( &(act.sa_mask), SIGPIPE ); |
253 | act.sa_flags = 0; | 252 | act.sa_flags = 0; |
254 | if ( sigaction( SIGPIPE, &act, &oldactPipe ) != 0 ) | 253 | if ( sigaction( SIGPIPE, &act, &oldactPipe ) != 0 ) |
255 | qWarning( "Error installing SIGPIPE handler" ); | 254 | owarn << "Error installing SIGPIPE handler" << oendl; |
256 | } | 255 | } |
257 | 256 | ||
258 | QProcessManager::~QProcessManager() | 257 | QProcessManager::~QProcessManager() |
259 | { | 258 | { |
260 | delete procList; | 259 | delete procList; |
261 | 260 | ||
262 | if ( sigchldFd[0] != 0 ) | 261 | if ( sigchldFd[0] != 0 ) |
263 | ::close( sigchldFd[0] ); | 262 | ::close( sigchldFd[0] ); |
264 | if ( sigchldFd[1] != 0 ) | 263 | if ( sigchldFd[1] != 0 ) |
265 | ::close( sigchldFd[1] ); | 264 | ::close( sigchldFd[1] ); |
266 | 265 | ||
267 | // restore SIGCHLD handler | 266 | // restore SIGCHLD handler |
268 | #if defined(QT_QPROCESS_DEBUG) | 267 | #if defined(QT_QPROCESS_DEBUG) |
269 | qDebug( "QProcessManager: restore old sigchild handler" ); | 268 | odebug << "QProcessManager: restore old sigchild handler" << oendl; |
270 | #endif | 269 | #endif |
271 | if ( sigaction( SIGCHLD, &oldactChld, 0 ) != 0 ) | 270 | if ( sigaction( SIGCHLD, &oldactChld, 0 ) != 0 ) |
272 | qWarning( "Error restoring SIGCHLD handler" ); | 271 | owarn << "Error restoring SIGCHLD handler" << oendl; |
273 | 272 | ||
274 | #if defined(QT_QPROCESS_DEBUG) | 273 | #if defined(QT_QPROCESS_DEBUG) |
275 | qDebug( "QProcessManager: restore old sigpipe handler" ); | 274 | odebug << "QProcessManager: restore old sigpipe handler" << oendl; |
276 | #endif | 275 | #endif |
277 | if ( sigaction( SIGPIPE, &oldactPipe, 0 ) != 0 ) | 276 | if ( sigaction( SIGPIPE, &oldactPipe, 0 ) != 0 ) |
278 | qWarning( "Error restoring SIGPIPE handler" ); | 277 | owarn << "Error restoring SIGPIPE handler" << oendl; |
279 | } | 278 | } |
280 | 279 | ||
281 | void QProcessManager::append( QProc *p ) | 280 | void QProcessManager::append( QProc *p ) |
282 | { | 281 | { |
283 | procList->append( p ); | 282 | procList->append( p ); |
284 | #if defined(QT_QPROCESS_DEBUG) | 283 | #if defined(QT_QPROCESS_DEBUG) |
285 | qDebug( "QProcessManager: append process (procList.count(): %d)", procList->count() ); | 284 | odebug << "QProcessManager: append process (procList.count(): " << procList->count() << ")" << oendl; |
286 | #endif | 285 | #endif |
287 | } | 286 | } |
288 | 287 | ||
289 | void QProcessManager::remove( QProc *p ) | 288 | void QProcessManager::remove( QProc *p ) |
290 | { | 289 | { |
291 | procList->remove( p ); | 290 | procList->remove( p ); |
292 | #if defined(QT_QPROCESS_DEBUG) | 291 | #if defined(QT_QPROCESS_DEBUG) |
293 | qDebug( "QProcessManager: remove process (procList.count(): %d)", procList->count() ); | 292 | odebug << "QProcessManager: remove process (procList.count(): " << procList->count() << ")" << oendl; |
294 | #endif | 293 | #endif |
295 | cleanup(); | 294 | cleanup(); |
296 | } | 295 | } |
297 | 296 | ||
298 | void QProcessManager::cleanup() | 297 | void QProcessManager::cleanup() |
299 | { | 298 | { |
300 | if ( procList->count() == 0 ) { | 299 | if ( procList->count() == 0 ) { |
301 | QTimer::singleShot( 0, this, SLOT(removeMe()) ); | 300 | QTimer::singleShot( 0, this, SLOT(removeMe()) ); |
302 | } | 301 | } |
303 | } | 302 | } |
304 | 303 | ||
305 | void QProcessManager::removeMe() | 304 | void QProcessManager::removeMe() |
@@ -307,65 +306,65 @@ void QProcessManager::removeMe() | |||
307 | if ( procList->count() == 0 ) { | 306 | if ( procList->count() == 0 ) { |
308 | qprocess_cleanup_procmanager.remove( &QProcessPrivate::procManager ); | 307 | qprocess_cleanup_procmanager.remove( &QProcessPrivate::procManager ); |
309 | QProcessPrivate::procManager = 0; | 308 | QProcessPrivate::procManager = 0; |
310 | delete this; | 309 | delete this; |
311 | } | 310 | } |
312 | } | 311 | } |
313 | 312 | ||
314 | void QProcessManager::sigchldHnd( int fd ) | 313 | void QProcessManager::sigchldHnd( int fd ) |
315 | { | 314 | { |
316 | char tmp; | 315 | char tmp; |
317 | ::read( fd, &tmp, sizeof(tmp) ); | 316 | ::read( fd, &tmp, sizeof(tmp) ); |
318 | #if defined(QT_QPROCESS_DEBUG) | 317 | #if defined(QT_QPROCESS_DEBUG) |
319 | qDebug( "QProcessManager::sigchldHnd()" ); | 318 | odebug << "QProcessManager::sigchldHnd()" << oendl; |
320 | #endif | 319 | #endif |
321 | QProc *proc; | 320 | QProc *proc; |
322 | QProcess *process; | 321 | QProcess *process; |
323 | bool removeProc; | 322 | bool removeProc; |
324 | proc = procList->first(); | 323 | proc = procList->first(); |
325 | while ( proc != 0 ) { | 324 | while ( proc != 0 ) { |
326 | removeProc = FALSE; | 325 | removeProc = FALSE; |
327 | process = proc->process; | 326 | process = proc->process; |
328 | QProcess *process_exit_notify=0; | 327 | QProcess *process_exit_notify=0; |
329 | if ( process != 0 ) { | 328 | if ( process != 0 ) { |
330 | if ( !process->isRunning() ) { | 329 | if ( !process->isRunning() ) { |
331 | #if defined(QT_QPROCESS_DEBUG) | 330 | #if defined(QT_QPROCESS_DEBUG) |
332 | qDebug( "QProcessManager::sigchldHnd() (PID: %d): process exited (QProcess available)", proc->pid ); | 331 | odebug << "QProcessManager::sigchldHnd() (PID: " << proc->pid << "): process exited (QProcess available)" << oendl; |
333 | #endif | 332 | #endif |
334 | // read pending data | 333 | // read pending data |
335 | int nbytes = 0; | 334 | int nbytes = 0; |
336 | if ( ::ioctl(proc->socketStdout, FIONREAD, (char*)&nbytes)==0 && nbytes>0 ) { | 335 | if ( ::ioctl(proc->socketStdout, FIONREAD, (char*)&nbytes)==0 && nbytes>0 ) { |
337 | #if defined(QT_QPROCESS_DEBUG) | 336 | #if defined(QT_QPROCESS_DEBUG) |
338 | qDebug( "QProcessManager::sigchldHnd() (PID: %d): reading %d bytes of pending data on stdout", proc->pid, nbytes ); | 337 | odebug << "QProcessManager::sigchldHnd() (PID: " << proc->pid << "): reading " << nbytes << " bytes of pending data on stdout" << oendl; |
339 | #endif | 338 | #endif |
340 | process->socketRead( proc->socketStdout ); | 339 | process->socketRead( proc->socketStdout ); |
341 | } | 340 | } |
342 | nbytes = 0; | 341 | nbytes = 0; |
343 | if ( ::ioctl(proc->socketStderr, FIONREAD, (char*)&nbytes)==0 && nbytes>0 ) { | 342 | if ( ::ioctl(proc->socketStderr, FIONREAD, (char*)&nbytes)==0 && nbytes>0 ) { |
344 | #if defined(QT_QPROCESS_DEBUG) | 343 | #if defined(QT_QPROCESS_DEBUG) |
345 | qDebug( "QProcessManager::sigchldHnd() (PID: %d): reading %d bytes of pending data on stderr", proc->pid, nbytes ); | 344 | odebug << "QProcessManager::sigchldHnd() (PID: " << proc->pid << "): reading " << nbytes << " bytes of pending data on stderr" << oendl; |
346 | #endif | 345 | #endif |
347 | process->socketRead( proc->socketStderr ); | 346 | process->socketRead( proc->socketStderr ); |
348 | } | 347 | } |
349 | 348 | ||
350 | if ( process->notifyOnExit ) | 349 | if ( process->notifyOnExit ) |
351 | process_exit_notify = process; | 350 | process_exit_notify = process; |
352 | 351 | ||
353 | removeProc = TRUE; | 352 | removeProc = TRUE; |
354 | } | 353 | } |
355 | } else { | 354 | } else { |
356 | int status; | 355 | int status; |
357 | if ( ::waitpid( proc->pid, &status, WNOHANG ) == proc->pid ) { | 356 | if ( ::waitpid( proc->pid, &status, WNOHANG ) == proc->pid ) { |
358 | #if defined(QT_QPROCESS_DEBUG) | 357 | #if defined(QT_QPROCESS_DEBUG) |
359 | qDebug( "QProcessManager::sigchldHnd() (PID: %d): process exited (QProcess not available)", proc->pid ); | 358 | odebug << "QProcessManager::sigchldHnd() (PID: " << proc->pid << "): process exited (QProcess not available)" << oendl; |
360 | #endif | 359 | #endif |
361 | removeProc = TRUE; | 360 | removeProc = TRUE; |
362 | } | 361 | } |
363 | } | 362 | } |
364 | if ( removeProc ) { | 363 | if ( removeProc ) { |
365 | QProc *oldproc = proc; | 364 | QProc *oldproc = proc; |
366 | proc = procList->next(); | 365 | proc = procList->next(); |
367 | remove( oldproc ); | 366 | remove( oldproc ); |
368 | } else { | 367 | } else { |
369 | proc = procList->next(); | 368 | proc = procList->next(); |
370 | } | 369 | } |
371 | if ( process_exit_notify ) | 370 | if ( process_exit_notify ) |
@@ -377,42 +376,42 @@ void QProcessManager::sigchldHnd( int fd ) | |||
377 | 376 | ||
378 | 377 | ||
379 | /*********************************************************************** | 378 | /*********************************************************************** |
380 | * | 379 | * |
381 | * QProcessPrivate | 380 | * QProcessPrivate |
382 | * | 381 | * |
383 | **********************************************************************/ | 382 | **********************************************************************/ |
384 | QProcessManager *QProcessPrivate::procManager = 0; | 383 | QProcessManager *QProcessPrivate::procManager = 0; |
385 | 384 | ||
386 | QProcessPrivate::QProcessPrivate() | 385 | QProcessPrivate::QProcessPrivate() |
387 | { | 386 | { |
388 | #if defined(QT_QPROCESS_DEBUG) | 387 | #if defined(QT_QPROCESS_DEBUG) |
389 | qDebug( "QProcessPrivate: Constructor" ); | 388 | odebug << "QProcessPrivate: Constructor" << oendl; |
390 | #endif | 389 | #endif |
391 | stdinBufRead = 0; | 390 | stdinBufRead = 0; |
392 | 391 | ||
393 | notifierStdin = 0; | 392 | notifierStdin = 0; |
394 | notifierStdout = 0; | 393 | notifierStdout = 0; |
395 | notifierStderr = 0; | 394 | notifierStderr = 0; |
396 | 395 | ||
397 | exitValuesCalculated = FALSE; | 396 | exitValuesCalculated = FALSE; |
398 | socketReadCalled = FALSE; | 397 | socketReadCalled = FALSE; |
399 | 398 | ||
400 | proc = 0; | 399 | proc = 0; |
401 | } | 400 | } |
402 | 401 | ||
403 | QProcessPrivate::~QProcessPrivate() | 402 | QProcessPrivate::~QProcessPrivate() |
404 | { | 403 | { |
405 | #if defined(QT_QPROCESS_DEBUG) | 404 | #if defined(QT_QPROCESS_DEBUG) |
406 | qDebug( "QProcessPrivate: Destructor" ); | 405 | odebug << "QProcessPrivate: Destructor" << oendl; |
407 | #endif | 406 | #endif |
408 | 407 | ||
409 | if ( proc != 0 ) { | 408 | if ( proc != 0 ) { |
410 | if ( proc->socketStdin != 0 ) { | 409 | if ( proc->socketStdin != 0 ) { |
411 | ::close( proc->socketStdin ); | 410 | ::close( proc->socketStdin ); |
412 | proc->socketStdin = 0; | 411 | proc->socketStdin = 0; |
413 | } | 412 | } |
414 | proc->process = 0; | 413 | proc->process = 0; |
415 | } | 414 | } |
416 | 415 | ||
417 | while ( !stdinBuf.isEmpty() ) { | 416 | while ( !stdinBuf.isEmpty() ) { |
418 | delete stdinBuf.dequeue(); | 417 | delete stdinBuf.dequeue(); |
@@ -590,25 +589,25 @@ QProcess::~QProcess() | |||
590 | You can call this function even when there already is a running | 589 | You can call this function even when there already is a running |
591 | process in this object. In this case, QProcess closes standard input | 590 | process in this object. In this case, QProcess closes standard input |
592 | of the old process and deletes pending data, i.e., you loose all | 591 | of the old process and deletes pending data, i.e., you loose all |
593 | control over that process, but the process is not terminated. This applies | 592 | control over that process, but the process is not terminated. This applies |
594 | also if the process could not be started. (On operating systems that have | 593 | also if the process could not be started. (On operating systems that have |
595 | zombie processes, Qt will also wait() on the old process.) | 594 | zombie processes, Qt will also wait() on the old process.) |
596 | 595 | ||
597 | \sa launch() closeStdin() | 596 | \sa launch() closeStdin() |
598 | */ | 597 | */ |
599 | bool QProcess::start( QStringList *env ) | 598 | bool QProcess::start( QStringList *env ) |
600 | { | 599 | { |
601 | #if defined(QT_QPROCESS_DEBUG) | 600 | #if defined(QT_QPROCESS_DEBUG) |
602 | qDebug( "QProcess::start()" ); | 601 | odebug << "QProcess::start()" << oendl; |
603 | #endif | 602 | #endif |
604 | reset(); | 603 | reset(); |
605 | 604 | ||
606 | int sStdin[2]; | 605 | int sStdin[2]; |
607 | int sStdout[2]; | 606 | int sStdout[2]; |
608 | int sStderr[2]; | 607 | int sStderr[2]; |
609 | 608 | ||
610 | // open sockets for piping | 609 | // open sockets for piping |
611 | if ( (comms & Stdin) && ::socketpair( AF_UNIX, SOCK_STREAM, 0, sStdin ) == -1 ) { | 610 | if ( (comms & Stdin) && ::socketpair( AF_UNIX, SOCK_STREAM, 0, sStdin ) == -1 ) { |
612 | return FALSE; | 611 | return FALSE; |
613 | } | 612 | } |
614 | if ( (comms & Stderr) && ::socketpair( AF_UNIX, SOCK_STREAM, 0, sStderr ) == -1 ) { | 613 | if ( (comms & Stderr) && ::socketpair( AF_UNIX, SOCK_STREAM, 0, sStderr ) == -1 ) { |
@@ -626,25 +625,25 @@ bool QProcess::start( QStringList *env ) | |||
626 | fd[0] = 0; | 625 | fd[0] = 0; |
627 | fd[1] = 0; | 626 | fd[1] = 0; |
628 | } | 627 | } |
629 | 628 | ||
630 | // construct the arguments for exec | 629 | // construct the arguments for exec |
631 | QCString *arglistQ = new QCString[ _arguments.count() + 1 ]; | 630 | QCString *arglistQ = new QCString[ _arguments.count() + 1 ]; |
632 | const char** arglist = new const char*[ _arguments.count() + 1 ]; | 631 | const char** arglist = new const char*[ _arguments.count() + 1 ]; |
633 | int i = 0; | 632 | int i = 0; |
634 | for ( QStringList::Iterator it = _arguments.begin(); it != _arguments.end(); ++it ) { | 633 | for ( QStringList::Iterator it = _arguments.begin(); it != _arguments.end(); ++it ) { |
635 | arglistQ[i] = (*it).local8Bit(); | 634 | arglistQ[i] = (*it).local8Bit(); |
636 | arglist[i] = arglistQ[i]; | 635 | arglist[i] = arglistQ[i]; |
637 | #if defined(QT_QPROCESS_DEBUG) | 636 | #if defined(QT_QPROCESS_DEBUG) |
638 | qDebug( "QProcess::start(): arg %d = %s", i, arglist[i] ); | 637 | odebug << "QProcess::start(): arg " << i << " = " << arglist[i] << "" << oendl; |
639 | #endif | 638 | #endif |
640 | i++; | 639 | i++; |
641 | } | 640 | } |
642 | arglist[i] = 0; | 641 | arglist[i] = 0; |
643 | 642 | ||
644 | // Must make sure signal handlers are installed before exec'ing | 643 | // Must make sure signal handlers are installed before exec'ing |
645 | // in case the process exits quickly. | 644 | // in case the process exits quickly. |
646 | if ( d->procManager == 0 ) { | 645 | if ( d->procManager == 0 ) { |
647 | d->procManager = new QProcessManager; | 646 | d->procManager = new QProcessManager; |
648 | qprocess_cleanup_procmanager.add( &d->procManager ); | 647 | qprocess_cleanup_procmanager.add( &d->procManager ); |
649 | } | 648 | } |
650 | 649 | ||
@@ -790,25 +789,25 @@ bool QProcess::start( QStringList *env ) | |||
790 | this, SLOT(socketRead(int)) ); | 789 | this, SLOT(socketRead(int)) ); |
791 | if ( ioRedirection ) | 790 | if ( ioRedirection ) |
792 | d->notifierStderr->setEnabled( TRUE ); | 791 | d->notifierStderr->setEnabled( TRUE ); |
793 | } | 792 | } |
794 | 793 | ||
795 | // cleanup and return | 794 | // cleanup and return |
796 | delete[] arglistQ; | 795 | delete[] arglistQ; |
797 | delete[] arglist; | 796 | delete[] arglist; |
798 | return TRUE; | 797 | return TRUE; |
799 | 798 | ||
800 | error: | 799 | error: |
801 | #if defined(QT_QPROCESS_DEBUG) | 800 | #if defined(QT_QPROCESS_DEBUG) |
802 | qDebug( "QProcess::start(): error starting process" ); | 801 | odebug << "QProcess::start(): error starting process" << oendl; |
803 | #endif | 802 | #endif |
804 | if ( d->procManager ) | 803 | if ( d->procManager ) |
805 | d->procManager->cleanup(); | 804 | d->procManager->cleanup(); |
806 | if ( comms & Stdin ) { | 805 | if ( comms & Stdin ) { |
807 | ::close( sStdin[1] ); | 806 | ::close( sStdin[1] ); |
808 | ::close( sStdin[0] ); | 807 | ::close( sStdin[0] ); |
809 | } | 808 | } |
810 | if ( comms & Stdout ) { | 809 | if ( comms & Stdout ) { |
811 | ::close( sStdout[0] ); | 810 | ::close( sStdout[0] ); |
812 | ::close( sStdout[1] ); | 811 | ::close( sStdout[1] ); |
813 | } | 812 | } |
814 | if ( comms & Stderr ) { | 813 | if ( comms & Stderr ) { |
@@ -869,67 +868,67 @@ void QProcess::kill() const | |||
869 | ::kill( d->proc->pid, SIGKILL ); | 868 | ::kill( d->proc->pid, SIGKILL ); |
870 | } | 869 | } |
871 | 870 | ||
872 | /*! | 871 | /*! |
873 | Returns TRUE if the process is running, otherwise FALSE. | 872 | Returns TRUE if the process is running, otherwise FALSE. |
874 | 873 | ||
875 | \sa normalExit() exitStatus() processExited() | 874 | \sa normalExit() exitStatus() processExited() |
876 | */ | 875 | */ |
877 | bool QProcess::isRunning() const | 876 | bool QProcess::isRunning() const |
878 | { | 877 | { |
879 | if ( d->exitValuesCalculated ) { | 878 | if ( d->exitValuesCalculated ) { |
880 | #if defined(QT_QPROCESS_DEBUG) | 879 | #if defined(QT_QPROCESS_DEBUG) |
881 | qDebug( "QProcess::isRunning(): FALSE (already computed)" ); | 880 | odebug << "QProcess::isRunning(): FALSE (already computed)" << oendl; |
882 | #endif | 881 | #endif |
883 | return FALSE; | 882 | return FALSE; |
884 | } | 883 | } |
885 | if ( d->proc == 0 ) | 884 | if ( d->proc == 0 ) |
886 | return FALSE; | 885 | return FALSE; |
887 | int status; | 886 | int status; |
888 | if ( ::waitpid( d->proc->pid, &status, WNOHANG ) == d->proc->pid ) | 887 | if ( ::waitpid( d->proc->pid, &status, WNOHANG ) == d->proc->pid ) |
889 | { | 888 | { |
890 | // compute the exit values | 889 | // compute the exit values |
891 | QProcess *that = (QProcess*)this; // mutable | 890 | QProcess *that = (QProcess*)this; // mutable |
892 | that->exitNormal = WIFEXITED( status ) != 0; | 891 | that->exitNormal = WIFEXITED( status ) != 0; |
893 | if ( exitNormal ) { | 892 | if ( exitNormal ) { |
894 | that->exitStat = (char)WEXITSTATUS( status ); | 893 | that->exitStat = (char)WEXITSTATUS( status ); |
895 | } | 894 | } |
896 | d->exitValuesCalculated = TRUE; | 895 | d->exitValuesCalculated = TRUE; |
897 | #if defined(QT_QPROCESS_DEBUG) | 896 | #if defined(QT_QPROCESS_DEBUG) |
898 | qDebug( "QProcess::isRunning() (PID: %d): FALSE", d->proc->pid ); | 897 | odebug << "QProcess::isRunning() (PID: " << d->proc->pid << "): FALSE" << oendl; |
899 | #endif | 898 | #endif |
900 | return FALSE; | 899 | return FALSE; |
901 | } | 900 | } |
902 | #if defined(QT_QPROCESS_DEBUG) | 901 | #if defined(QT_QPROCESS_DEBUG) |
903 | qDebug( "QProcess::isRunning() (PID: %d): TRUE", d->proc->pid ); | 902 | odebug << "QProcess::isRunning() (PID: " << d->proc->pid << "): TRUE" << oendl; |
904 | #endif | 903 | #endif |
905 | return TRUE; | 904 | return TRUE; |
906 | } | 905 | } |
907 | 906 | ||
908 | /*! | 907 | /*! |
909 | Writes the data \a buf to the standard input of the process. The process may | 908 | Writes the data \a buf to the standard input of the process. The process may |
910 | or may not read this data. | 909 | or may not read this data. |
911 | 910 | ||
912 | This function returns immediately; the QProcess class might write the data at | 911 | This function returns immediately; the QProcess class might write the data at |
913 | a later point (you have to enter the event loop for that). When all the data | 912 | a later point (you have to enter the event loop for that). When all the data |
914 | is written to the process, the signal wroteToStdin() is emitted. This does | 913 | is written to the process, the signal wroteToStdin() is emitted. This does |
915 | not mean that the process really read the data, since this class only detects | 914 | not mean that the process really read the data, since this class only detects |
916 | when it was able to write the data to the operating system. | 915 | when it was able to write the data to the operating system. |
917 | 916 | ||
918 | \sa wroteToStdin() closeStdin() readStdout() readStderr() | 917 | \sa wroteToStdin() closeStdin() readStdout() readStderr() |
919 | */ | 918 | */ |
920 | void QProcess::writeToStdin( const QByteArray& buf ) | 919 | void QProcess::writeToStdin( const QByteArray& buf ) |
921 | { | 920 | { |
922 | #if defined(QT_QPROCESS_DEBUG) | 921 | #if defined(QT_QPROCESS_DEBUG) |
923 | // qDebug( "QProcess::writeToStdin(): write to stdin (%d)", d->socketStdin ); | 922 | // odebug << "QProcess::writeToStdin(): write to stdin (" << d->socketStdin << ")" << oendl; |
924 | #endif | 923 | #endif |
925 | d->stdinBuf.enqueue( new QByteArray(buf) ); | 924 | d->stdinBuf.enqueue( new QByteArray(buf) ); |
926 | if ( d->notifierStdin != 0 ) | 925 | if ( d->notifierStdin != 0 ) |
927 | d->notifierStdin->setEnabled( TRUE ); | 926 | d->notifierStdin->setEnabled( TRUE ); |
928 | } | 927 | } |
929 | 928 | ||
930 | 929 | ||
931 | /*! | 930 | /*! |
932 | Closes standard input of the process. | 931 | Closes standard input of the process. |
933 | 932 | ||
934 | This function also deletes pending data that is not written to standard input | 933 | This function also deletes pending data that is not written to standard input |
935 | yet. | 934 | yet. |
@@ -938,48 +937,48 @@ void QProcess::writeToStdin( const QByteArray& buf ) | |||
938 | */ | 937 | */ |
939 | void QProcess::closeStdin() | 938 | void QProcess::closeStdin() |
940 | { | 939 | { |
941 | if ( d->proc == 0 ) | 940 | if ( d->proc == 0 ) |
942 | return; | 941 | return; |
943 | if ( d->proc->socketStdin !=0 ) { | 942 | if ( d->proc->socketStdin !=0 ) { |
944 | while ( !d->stdinBuf.isEmpty() ) { | 943 | while ( !d->stdinBuf.isEmpty() ) { |
945 | delete d->stdinBuf.dequeue(); | 944 | delete d->stdinBuf.dequeue(); |
946 | } | 945 | } |
947 | delete d->notifierStdin; | 946 | delete d->notifierStdin; |
948 | d->notifierStdin = 0; | 947 | d->notifierStdin = 0; |
949 | if ( ::close( d->proc->socketStdin ) != 0 ) { | 948 | if ( ::close( d->proc->socketStdin ) != 0 ) { |
950 | qWarning( "Could not close stdin of child process" ); | 949 | owarn << "Could not close stdin of child process" << oendl; |
951 | } | 950 | } |
952 | #if defined(QT_QPROCESS_DEBUG) | 951 | #if defined(QT_QPROCESS_DEBUG) |
953 | qDebug( "QProcess::closeStdin(): stdin (%d) closed", d->proc->socketStdin ); | 952 | odebug << "QProcess::closeStdin(): stdin (" << d->proc->socketStdin << ") closed" << oendl; |
954 | #endif | 953 | #endif |
955 | d->proc->socketStdin = 0; | 954 | d->proc->socketStdin = 0; |
956 | } | 955 | } |
957 | } | 956 | } |
958 | 957 | ||
959 | 958 | ||
960 | /* | 959 | /* |
961 | This private slot is called when the process has outputted data to either | 960 | This private slot is called when the process has outputted data to either |
962 | standard output or standard error. | 961 | standard output or standard error. |
963 | */ | 962 | */ |
964 | void QProcess::socketRead( int fd ) | 963 | void QProcess::socketRead( int fd ) |
965 | { | 964 | { |
966 | if ( d->socketReadCalled ) { | 965 | if ( d->socketReadCalled ) { |
967 | // the slots that are connected to the readyRead...() signals might | 966 | // the slots that are connected to the readyRead...() signals might |
968 | // trigger a recursive call of socketRead(). Avoid this since you get a | 967 | // trigger a recursive call of socketRead(). Avoid this since you get a |
969 | // blocking read otherwise. | 968 | // blocking read otherwise. |
970 | return; | 969 | return; |
971 | } | 970 | } |
972 | #if defined(QT_QPROCESS_DEBUG) | 971 | #if defined(QT_QPROCESS_DEBUG) |
973 | qDebug( "QProcess::socketRead(): %d", fd ); | 972 | odebug << "QProcess::socketRead(): " << fd << "" << oendl; |
974 | #endif | 973 | #endif |
975 | if ( fd == 0 ) | 974 | if ( fd == 0 ) |
976 | return; | 975 | return; |
977 | const int bufsize = 4096; | 976 | const int bufsize = 4096; |
978 | QByteArray *buffer = 0; | 977 | QByteArray *buffer = 0; |
979 | uint oldSize; | 978 | uint oldSize; |
980 | int n; | 979 | int n; |
981 | if ( fd == d->proc->socketStdout ) { | 980 | if ( fd == d->proc->socketStdout ) { |
982 | buffer = &d->bufStdout; | 981 | buffer = &d->bufStdout; |
983 | } else if ( fd == d->proc->socketStderr ) { | 982 | } else if ( fd == d->proc->socketStderr ) { |
984 | buffer = &d->bufStderr; | 983 | buffer = &d->bufStderr; |
985 | } else { | 984 | } else { |
@@ -990,35 +989,35 @@ void QProcess::socketRead( int fd ) | |||
990 | // read data | 989 | // read data |
991 | oldSize = buffer->size(); | 990 | oldSize = buffer->size(); |
992 | buffer->resize( oldSize + bufsize ); | 991 | buffer->resize( oldSize + bufsize ); |
993 | n = ::read( fd, buffer->data()+oldSize, bufsize ); | 992 | n = ::read( fd, buffer->data()+oldSize, bufsize ); |
994 | if ( n > 0 ) | 993 | if ( n > 0 ) |
995 | buffer->resize( oldSize + n ); | 994 | buffer->resize( oldSize + n ); |
996 | else | 995 | else |
997 | buffer->resize( oldSize ); | 996 | buffer->resize( oldSize ); |
998 | // eof or error? | 997 | // eof or error? |
999 | if ( n == 0 || n == -1 ) { | 998 | if ( n == 0 || n == -1 ) { |
1000 | if ( fd == d->proc->socketStdout ) { | 999 | if ( fd == d->proc->socketStdout ) { |
1001 | #if defined(QT_QPROCESS_DEBUG) | 1000 | #if defined(QT_QPROCESS_DEBUG) |
1002 | qDebug( "QProcess::socketRead(): stdout (%d) closed", fd ); | 1001 | odebug << "QProcess::socketRead(): stdout (" << fd << ") closed" << oendl; |
1003 | #endif | 1002 | #endif |
1004 | d->notifierStdout->setEnabled( FALSE ); | 1003 | d->notifierStdout->setEnabled( FALSE ); |
1005 | delete d->notifierStdout; | 1004 | delete d->notifierStdout; |
1006 | d->notifierStdout = 0; | 1005 | d->notifierStdout = 0; |
1007 | ::close( d->proc->socketStdout ); | 1006 | ::close( d->proc->socketStdout ); |
1008 | d->proc->socketStdout = 0; | 1007 | d->proc->socketStdout = 0; |
1009 | return; | 1008 | return; |
1010 | } else if ( fd == d->proc->socketStderr ) { | 1009 | } else if ( fd == d->proc->socketStderr ) { |
1011 | #if defined(QT_QPROCESS_DEBUG) | 1010 | #if defined(QT_QPROCESS_DEBUG) |
1012 | qDebug( "QProcess::socketRead(): stderr (%d) closed", fd ); | 1011 | odebug << "QProcess::socketRead(): stderr (" << fd << ") closed" << oendl; |
1013 | #endif | 1012 | #endif |
1014 | d->notifierStderr->setEnabled( FALSE ); | 1013 | d->notifierStderr->setEnabled( FALSE ); |
1015 | delete d->notifierStderr; | 1014 | delete d->notifierStderr; |
1016 | d->notifierStderr = 0; | 1015 | d->notifierStderr = 0; |
1017 | ::close( d->proc->socketStderr ); | 1016 | ::close( d->proc->socketStderr ); |
1018 | d->proc->socketStderr = 0; | 1017 | d->proc->socketStderr = 0; |
1019 | return; | 1018 | return; |
1020 | } | 1019 | } |
1021 | } | 1020 | } |
1022 | // read all data that is available | 1021 | // read all data that is available |
1023 | while ( n == bufsize ) { | 1022 | while ( n == bufsize ) { |
1024 | oldSize = buffer->size(); | 1023 | oldSize = buffer->size(); |
@@ -1052,25 +1051,25 @@ void QProcess::socketRead( int fd ) | |||
1052 | This private slot is called when the process tries to read data from standard | 1051 | This private slot is called when the process tries to read data from standard |
1053 | input. | 1052 | input. |
1054 | */ | 1053 | */ |
1055 | void QProcess::socketWrite( int fd ) | 1054 | void QProcess::socketWrite( int fd ) |
1056 | { | 1055 | { |
1057 | if ( fd != d->proc->socketStdin || d->proc->socketStdin == 0 ) | 1056 | if ( fd != d->proc->socketStdin || d->proc->socketStdin == 0 ) |
1058 | return; | 1057 | return; |
1059 | if ( d->stdinBuf.isEmpty() ) { | 1058 | if ( d->stdinBuf.isEmpty() ) { |
1060 | d->notifierStdin->setEnabled( FALSE ); | 1059 | d->notifierStdin->setEnabled( FALSE ); |
1061 | return; | 1060 | return; |
1062 | } | 1061 | } |
1063 | #if defined(QT_QPROCESS_DEBUG) | 1062 | #if defined(QT_QPROCESS_DEBUG) |
1064 | qDebug( "QProcess::socketWrite(): write to stdin (%d)", fd ); | 1063 | odebug << "QProcess::socketWrite(): write to stdin (" << fd << ")" << oendl; |
1065 | #endif | 1064 | #endif |
1066 | ssize_t ret = ::write( fd, | 1065 | ssize_t ret = ::write( fd, |
1067 | d->stdinBuf.head()->data() + d->stdinBufRead, | 1066 | d->stdinBuf.head()->data() + d->stdinBufRead, |
1068 | d->stdinBuf.head()->size() - d->stdinBufRead ); | 1067 | d->stdinBuf.head()->size() - d->stdinBufRead ); |
1069 | if ( ret > 0 ) | 1068 | if ( ret > 0 ) |
1070 | d->stdinBufRead += ret; | 1069 | d->stdinBufRead += ret; |
1071 | if ( d->stdinBufRead == (ssize_t)d->stdinBuf.head()->size() ) { | 1070 | if ( d->stdinBufRead == (ssize_t)d->stdinBuf.head()->size() ) { |
1072 | d->stdinBufRead = 0; | 1071 | d->stdinBufRead = 0; |
1073 | delete d->stdinBuf.dequeue(); | 1072 | delete d->stdinBuf.dequeue(); |
1074 | if ( wroteToStdinConnected && d->stdinBuf.isEmpty() ) | 1073 | if ( wroteToStdinConnected && d->stdinBuf.isEmpty() ) |
1075 | emit wroteToStdin(); | 1074 | emit wroteToStdin(); |
1076 | socketWrite( fd ); | 1075 | socketWrite( fd ); |