summaryrefslogtreecommitdiff
Unidiff
Diffstat (more/less context) (ignore whitespace changes)
-rw-r--r--core/launcher/qprocess_unix.cpp2
1 files changed, 1 insertions, 1 deletions
diff --git a/core/launcher/qprocess_unix.cpp b/core/launcher/qprocess_unix.cpp
index d62e4e6..56e1b1d 100644
--- a/core/launcher/qprocess_unix.cpp
+++ b/core/launcher/qprocess_unix.cpp
@@ -1,311 +1,311 @@
1/********************************************************************** 1/**********************************************************************
2** Copyright (C) 2000-2002 Trolltech AS. All rights reserved. 2** Copyright (C) 2000-2002 Trolltech AS. All rights reserved.
3** 3**
4** This file is part of the Qtopia Environment. 4** This file is part of the Qtopia Environment.
5** 5**
6** This file may be distributed and/or modified under the terms of the 6** This file may be distributed and/or modified under the terms of the
7** GNU General Public License version 2 as published by the Free Software 7** GNU General Public License version 2 as published by the Free Software
8** Foundation and appearing in the file LICENSE.GPL included in the 8** Foundation and appearing in the file LICENSE.GPL included in the
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// Solaris redefines connect -> __xnet_connect with _XOPEN_SOURCE_EXTENDED. 21// Solaris redefines connect -> __xnet_connect with _XOPEN_SOURCE_EXTENDED.
22#if defined(connect) 22#if defined(connect)
23#undef connect 23#undef connect
24#endif 24#endif
25 25
26#include "qprocess.h" 26#include "qprocess.h"
27 27
28/* OPIE */ 28/* OPIE */
29#include <opie2/odebug.h> 29#include <opie2/odebug.h>
30using namespace Opie::Core; 30using namespace Opie::Core;
31 31
32/* QT */ 32/* QT */
33#ifndef QT_NO_PROCESS 33#ifndef QT_NO_PROCESS
34#include <qapplication.h> 34#include <qapplication.h>
35#include <qqueue.h> 35#include <qqueue.h>
36#include <qlist.h> 36#include <qlist.h>
37#include <qsocketnotifier.h> 37#include <qsocketnotifier.h>
38#include <qtimer.h> 38#include <qtimer.h>
39#include <qregexp.h> 39#include <qregexp.h>
40 40
41#include "qcleanuphandler_p.h" 41#include "qcleanuphandler_p.h"
42 42
43/* STD */ 43/* STD */
44#include <stdlib.h> 44#include <stdlib.h>
45#include <unistd.h> 45#include <unistd.h>
46#include <signal.h> 46#include <signal.h>
47#include <sys/socket.h> 47#include <sys/socket.h>
48#include <sys/ioctl.h> 48#include <sys/ioctl.h>
49#include <sys/wait.h> 49#include <sys/wait.h>
50#include <sys/fcntl.h> 50#include <sys/fcntl.h>
51#include <sys/resource.h>
52#include <errno.h> 51#include <errno.h>
53#ifdef Q_OS_MACX 52#ifdef Q_OS_MACX
54#include <sys/time.h> 53#include <sys/time.h>
55#endif 54#endif
55#include <sys/resource.h>
56 56
57#ifdef __MIPSEL__ 57#ifdef __MIPSEL__
58# ifndef SOCK_DGRAM 58# ifndef SOCK_DGRAM
59# define SOCK_DGRAM 1 59# define SOCK_DGRAM 1
60# endif 60# endif
61# ifndef SOCK_STREAM 61# ifndef SOCK_STREAM
62# define SOCK_STREAM 2 62# define SOCK_STREAM 2
63# endif 63# endif
64#endif 64#endif
65 65
66//#define QT_QPROCESS_DEBUG 66//#define QT_QPROCESS_DEBUG
67 67
68 68
69#ifdef Q_C_CALLBACKS 69#ifdef Q_C_CALLBACKS
70extern "C" { 70extern "C" {
71#endif // Q_C_CALLBACKS 71#endif // Q_C_CALLBACKS
72 72
73#define QT_SIGNAL_RETTYPE void 73#define QT_SIGNAL_RETTYPE void
74#define QT_SIGNAL_ARGS int 74#define QT_SIGNAL_ARGS int
75#define QT_SIGNAL_IGNORE SIG_IGN 75#define QT_SIGNAL_IGNORE SIG_IGN
76 76
77 QT_SIGNAL_RETTYPE qt_C_sigchldHnd(QT_SIGNAL_ARGS); 77 QT_SIGNAL_RETTYPE qt_C_sigchldHnd(QT_SIGNAL_ARGS);
78 QT_SIGNAL_RETTYPE qt_C_sigpipeHnd(QT_SIGNAL_ARGS); 78 QT_SIGNAL_RETTYPE qt_C_sigpipeHnd(QT_SIGNAL_ARGS);
79 79
80#ifdef Q_C_CALLBACKS 80#ifdef Q_C_CALLBACKS
81} 81}
82#endif // Q_C_CALLBACKS 82#endif // Q_C_CALLBACKS
83 83
84 84
85class QProc; 85class QProc;
86class QProcessManager; 86class QProcessManager;
87class QProcessPrivate 87class QProcessPrivate
88{ 88{
89public: 89public:
90 QProcessPrivate(); 90 QProcessPrivate();
91 ~QProcessPrivate(); 91 ~QProcessPrivate();
92 92
93 void closeOpenSocketsForChild(); 93 void closeOpenSocketsForChild();
94 void newProc( pid_t pid, QProcess *process ); 94 void newProc( pid_t pid, QProcess *process );
95 95
96 QByteArray bufStdout; 96 QByteArray bufStdout;
97 QByteArray bufStderr; 97 QByteArray bufStderr;
98 98
99 QQueue<QByteArray> stdinBuf; 99 QQueue<QByteArray> stdinBuf;
100 100
101 QSocketNotifier *notifierStdin; 101 QSocketNotifier *notifierStdin;
102 QSocketNotifier *notifierStdout; 102 QSocketNotifier *notifierStdout;
103 QSocketNotifier *notifierStderr; 103 QSocketNotifier *notifierStderr;
104 104
105 ssize_t stdinBufRead; 105 ssize_t stdinBufRead;
106 QProc *proc; 106 QProc *proc;
107 107
108 bool exitValuesCalculated; 108 bool exitValuesCalculated;
109 bool socketReadCalled; 109 bool socketReadCalled;
110 110
111 static QProcessManager *procManager; 111 static QProcessManager *procManager;
112}; 112};
113 113
114 114
115/*********************************************************************** 115/***********************************************************************
116 * 116 *
117 * QProc 117 * QProc
118 * 118 *
119 **********************************************************************/ 119 **********************************************************************/
120/* 120/*
121 The class QProcess does not necessarily map exactly to the running 121 The class QProcess does not necessarily map exactly to the running
122 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
123 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.
124 124
125 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
126 directly to a running child process. 126 directly to a running child process.
127*/ 127*/
128class QProc 128class QProc
129{ 129{
130public: 130public:
131 QProc( pid_t p, QProcess *proc=0 ) : pid(p), process(proc) 131 QProc( pid_t p, QProcess *proc=0 ) : pid(p), process(proc)
132 { 132 {
133#if defined(QT_QPROCESS_DEBUG) 133#if defined(QT_QPROCESS_DEBUG)
134 odebug << "QProc: Constructor for pid " << pid << " and QProcess " << process << "" << oendl; 134 odebug << "QProc: Constructor for pid " << pid << " and QProcess " << process << "" << oendl;
135#endif 135#endif
136 socketStdin = 0; 136 socketStdin = 0;
137 socketStdout = 0; 137 socketStdout = 0;
138 socketStderr = 0; 138 socketStderr = 0;
139 } 139 }
140 ~QProc() 140 ~QProc()
141 { 141 {
142#if defined(QT_QPROCESS_DEBUG) 142#if defined(QT_QPROCESS_DEBUG)
143 odebug << "QProc: Destructor for pid " << pid << " and QProcess " << process << "" << oendl; 143 odebug << "QProc: Destructor for pid " << pid << " and QProcess " << process << "" << oendl;
144#endif 144#endif
145 if ( process != 0 ) { 145 if ( process != 0 ) {
146 if ( process->d->notifierStdin ) 146 if ( process->d->notifierStdin )
147 process->d->notifierStdin->setEnabled( FALSE ); 147 process->d->notifierStdin->setEnabled( FALSE );
148 if ( process->d->notifierStdout ) 148 if ( process->d->notifierStdout )
149 process->d->notifierStdout->setEnabled( FALSE ); 149 process->d->notifierStdout->setEnabled( FALSE );
150 if ( process->d->notifierStderr ) 150 if ( process->d->notifierStderr )
151 process->d->notifierStderr->setEnabled( FALSE ); 151 process->d->notifierStderr->setEnabled( FALSE );
152 process->d->proc = 0; 152 process->d->proc = 0;
153 } 153 }
154 if( socketStdin != 0 ) 154 if( socketStdin != 0 )
155 ::close( socketStdin ); 155 ::close( socketStdin );
156 // ### close these sockets even on parent exit or is it better only on 156 // ### close these sockets even on parent exit or is it better only on
157 // sigchld (but what do I have to do with them on exit then)? 157 // sigchld (but what do I have to do with them on exit then)?
158 if( socketStdout != 0 ) 158 if( socketStdout != 0 )
159 ::close( socketStdout ); 159 ::close( socketStdout );
160 if( socketStderr != 0 ) 160 if( socketStderr != 0 )
161 ::close( socketStderr ); 161 ::close( socketStderr );
162 } 162 }
163 163
164 pid_t pid; 164 pid_t pid;
165 int socketStdin; 165 int socketStdin;
166 int socketStdout; 166 int socketStdout;
167 int socketStderr; 167 int socketStderr;
168 QProcess *process; 168 QProcess *process;
169}; 169};
170 170
171/*********************************************************************** 171/***********************************************************************
172 * 172 *
173 * QProcessManager 173 * QProcessManager
174 * 174 *
175 **********************************************************************/ 175 **********************************************************************/
176class QProcessManager : public QObject 176class QProcessManager : public QObject
177{ 177{
178 Q_OBJECT 178 Q_OBJECT
179 179
180public: 180public:
181 QProcessManager(); 181 QProcessManager();
182 ~QProcessManager(); 182 ~QProcessManager();
183 183
184 void append( QProc *p ); 184 void append( QProc *p );
185 void remove( QProc *p ); 185 void remove( QProc *p );
186 186
187 void cleanup(); 187 void cleanup();
188 188
189public slots: 189public slots:
190 void removeMe(); 190 void removeMe();
191 void sigchldHnd( int ); 191 void sigchldHnd( int );
192 192
193public: 193public:
194 struct sigaction oldactChld; 194 struct sigaction oldactChld;
195 struct sigaction oldactPipe; 195 struct sigaction oldactPipe;
196 QList<QProc> *procList; 196 QList<QProc> *procList;
197 int sigchldFd[2]; 197 int sigchldFd[2];
198}; 198};
199 199
200QCleanupHandler<QProcessManager> qprocess_cleanup_procmanager; 200QCleanupHandler<QProcessManager> qprocess_cleanup_procmanager;
201 201
202QProcessManager::QProcessManager() 202QProcessManager::QProcessManager()
203{ 203{
204 procList = new QList<QProc>; 204 procList = new QList<QProc>;
205 procList->setAutoDelete( TRUE ); 205 procList->setAutoDelete( TRUE );
206 206
207 // 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
208 // 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
209 // event reporting. 209 // event reporting.
210 if ( ::socketpair( AF_UNIX, SOCK_STREAM, 0, sigchldFd ) ) { 210 if ( ::socketpair( AF_UNIX, SOCK_STREAM, 0, sigchldFd ) ) {
211 sigchldFd[0] = 0; 211 sigchldFd[0] = 0;
212 sigchldFd[1] = 0; 212 sigchldFd[1] = 0;
213 } else { 213 } else {
214#if defined(QT_QPROCESS_DEBUG) 214#if defined(QT_QPROCESS_DEBUG)
215 odebug << "QProcessManager: install socket notifier (" << sigchldFd[1] << ")" << oendl; 215 odebug << "QProcessManager: install socket notifier (" << sigchldFd[1] << ")" << oendl;
216#endif 216#endif
217 QSocketNotifier *sn = new QSocketNotifier( sigchldFd[1], 217 QSocketNotifier *sn = new QSocketNotifier( sigchldFd[1],
218 QSocketNotifier::Read, this ); 218 QSocketNotifier::Read, this );
219 connect( sn, SIGNAL(activated(int)), 219 connect( sn, SIGNAL(activated(int)),
220 this, SLOT(sigchldHnd(int)) ); 220 this, SLOT(sigchldHnd(int)) );
221 sn->setEnabled( TRUE ); 221 sn->setEnabled( TRUE );
222 } 222 }
223 223
224 // install a SIGCHLD handler and ignore SIGPIPE 224 // install a SIGCHLD handler and ignore SIGPIPE
225 struct sigaction act; 225 struct sigaction act;
226 226
227#if defined(QT_QPROCESS_DEBUG) 227#if defined(QT_QPROCESS_DEBUG)
228 odebug << "QProcessManager: install a SIGCHLD handler" << oendl; 228 odebug << "QProcessManager: install a SIGCHLD handler" << oendl;
229#endif 229#endif
230 act.sa_handler = qt_C_sigchldHnd; 230 act.sa_handler = qt_C_sigchldHnd;
231 sigemptyset( &(act.sa_mask) ); 231 sigemptyset( &(act.sa_mask) );
232 sigaddset( &(act.sa_mask), SIGCHLD ); 232 sigaddset( &(act.sa_mask), SIGCHLD );
233 act.sa_flags = SA_NOCLDSTOP; 233 act.sa_flags = SA_NOCLDSTOP;
234#if defined(SA_RESTART) 234#if defined(SA_RESTART)
235 act.sa_flags |= SA_RESTART; 235 act.sa_flags |= SA_RESTART;
236#endif 236#endif
237 if ( sigaction( SIGCHLD, &act, &oldactChld ) != 0 ) 237 if ( sigaction( SIGCHLD, &act, &oldactChld ) != 0 )
238 owarn << "Error installing SIGCHLD handler" << oendl; 238 owarn << "Error installing SIGCHLD handler" << oendl;
239 239
240#if defined(QT_QPROCESS_DEBUG) 240#if defined(QT_QPROCESS_DEBUG)
241 odebug << "QProcessManager: install a SIGPIPE handler (SIG_IGN)" << oendl; 241 odebug << "QProcessManager: install a SIGPIPE handler (SIG_IGN)" << oendl;
242#endif 242#endif
243 /* 243 /*
244 Using qt_C_sigpipeHnd rather than SIG_IGN is a workaround 244 Using qt_C_sigpipeHnd rather than SIG_IGN is a workaround
245 for a strange problem where GNU tar (called by backuprestore) 245 for a strange problem where GNU tar (called by backuprestore)
246 would hang on filesystem-full. Strangely, the qt_C_sigpipeHnd 246 would hang on filesystem-full. Strangely, the qt_C_sigpipeHnd
247 is never even called, yet this avoids the hang. 247 is never even called, yet this avoids the hang.
248 */ 248 */
249 act.sa_handler = qt_C_sigpipeHnd; 249 act.sa_handler = qt_C_sigpipeHnd;
250 sigemptyset( &(act.sa_mask) ); 250 sigemptyset( &(act.sa_mask) );
251 sigaddset( &(act.sa_mask), SIGPIPE ); 251 sigaddset( &(act.sa_mask), SIGPIPE );
252 act.sa_flags = 0; 252 act.sa_flags = 0;
253 if ( sigaction( SIGPIPE, &act, &oldactPipe ) != 0 ) 253 if ( sigaction( SIGPIPE, &act, &oldactPipe ) != 0 )
254 owarn << "Error installing SIGPIPE handler" << oendl; 254 owarn << "Error installing SIGPIPE handler" << oendl;
255} 255}
256 256
257QProcessManager::~QProcessManager() 257QProcessManager::~QProcessManager()
258{ 258{
259 delete procList; 259 delete procList;
260 260
261 if ( sigchldFd[0] != 0 ) 261 if ( sigchldFd[0] != 0 )
262 ::close( sigchldFd[0] ); 262 ::close( sigchldFd[0] );
263 if ( sigchldFd[1] != 0 ) 263 if ( sigchldFd[1] != 0 )
264 ::close( sigchldFd[1] ); 264 ::close( sigchldFd[1] );
265 265
266 // restore SIGCHLD handler 266 // restore SIGCHLD handler
267#if defined(QT_QPROCESS_DEBUG) 267#if defined(QT_QPROCESS_DEBUG)
268 odebug << "QProcessManager: restore old sigchild handler" << oendl; 268 odebug << "QProcessManager: restore old sigchild handler" << oendl;
269#endif 269#endif
270 if ( sigaction( SIGCHLD, &oldactChld, 0 ) != 0 ) 270 if ( sigaction( SIGCHLD, &oldactChld, 0 ) != 0 )
271 owarn << "Error restoring SIGCHLD handler" << oendl; 271 owarn << "Error restoring SIGCHLD handler" << oendl;
272 272
273#if defined(QT_QPROCESS_DEBUG) 273#if defined(QT_QPROCESS_DEBUG)
274 odebug << "QProcessManager: restore old sigpipe handler" << oendl; 274 odebug << "QProcessManager: restore old sigpipe handler" << oendl;
275#endif 275#endif
276 if ( sigaction( SIGPIPE, &oldactPipe, 0 ) != 0 ) 276 if ( sigaction( SIGPIPE, &oldactPipe, 0 ) != 0 )
277 owarn << "Error restoring SIGPIPE handler" << oendl; 277 owarn << "Error restoring SIGPIPE handler" << oendl;
278} 278}
279 279
280void QProcessManager::append( QProc *p ) 280void QProcessManager::append( QProc *p )
281{ 281{
282 procList->append( p ); 282 procList->append( p );
283#if defined(QT_QPROCESS_DEBUG) 283#if defined(QT_QPROCESS_DEBUG)
284 odebug << "QProcessManager: append process (procList.count(): " << procList->count() << ")" << oendl; 284 odebug << "QProcessManager: append process (procList.count(): " << procList->count() << ")" << oendl;
285#endif 285#endif
286} 286}
287 287
288void QProcessManager::remove( QProc *p ) 288void QProcessManager::remove( QProc *p )
289{ 289{
290 procList->remove( p ); 290 procList->remove( p );
291#if defined(QT_QPROCESS_DEBUG) 291#if defined(QT_QPROCESS_DEBUG)
292 odebug << "QProcessManager: remove process (procList.count(): " << procList->count() << ")" << oendl; 292 odebug << "QProcessManager: remove process (procList.count(): " << procList->count() << ")" << oendl;
293#endif 293#endif
294 cleanup(); 294 cleanup();
295} 295}
296 296
297void QProcessManager::cleanup() 297void QProcessManager::cleanup()
298{ 298{
299 if ( procList->count() == 0 ) { 299 if ( procList->count() == 0 ) {
300 QTimer::singleShot( 0, this, SLOT(removeMe()) ); 300 QTimer::singleShot( 0, this, SLOT(removeMe()) );
301 } 301 }
302} 302}
303 303
304void QProcessManager::removeMe() 304void QProcessManager::removeMe()
305{ 305{
306 if ( procList->count() == 0 ) { 306 if ( procList->count() == 0 ) {
307 qprocess_cleanup_procmanager.remove( &QProcessPrivate::procManager ); 307 qprocess_cleanup_procmanager.remove( &QProcessPrivate::procManager );
308 QProcessPrivate::procManager = 0; 308 QProcessPrivate::procManager = 0;
309 delete this; 309 delete this;
310 } 310 }
311} 311}