summaryrefslogtreecommitdiff
path: root/core/launcher/qprocess_unix.cpp
Side-by-side diff
Diffstat (limited to 'core/launcher/qprocess_unix.cpp') (more/less context) (ignore whitespace changes)
-rw-r--r--core/launcher/qprocess_unix.cpp93
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 @@
** packaging of this file.
**
** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
**
** See http://www.trolltech.com/gpl/ for GPL licensing information.
**
** Contact info@trolltech.com if any conditions of this licensing are
** not clear to you.
**
**********************************************************************/
-//#include "qplatformdefs.h"
-
// Solaris redefines connect -> __xnet_connect with _XOPEN_SOURCE_EXTENDED.
#if defined(connect)
#undef connect
#endif
#include "qprocess.h"
-#ifndef QT_NO_PROCESS
+/* OPIE */
+#include <opie2/odebug.h>
+using namespace Opie::Core;
-#include "qapplication.h"
-#include "qqueue.h"
-#include "qlist.h"
-#include "qsocketnotifier.h"
-#include "qtimer.h"
-#include "qregexp.h"
+/* QT */
+#ifndef QT_NO_PROCESS
+#include <qapplication.h>
+#include <qqueue.h>
+#include <qlist.h>
+#include <qsocketnotifier.h>
+#include <qtimer.h>
+#include <qregexp.h>
#include "qcleanuphandler_p.h"
+/* STD */
#include <stdlib.h>
-
-// ### FOR Qt 2.3 compat
#include <unistd.h>
#include <signal.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <sys/wait.h>
#include <sys/fcntl.h>
-
+#include <sys/resource.h>
#include <errno.h>
-
#ifdef Q_OS_MACX
#include <sys/time.h>
#endif
-#include <sys/resource.h>
#ifdef __MIPSEL__
# ifndef SOCK_DGRAM
# define SOCK_DGRAM 1
# endif
# ifndef SOCK_STREAM
# define SOCK_STREAM 2
# endif
#endif
//#define QT_QPROCESS_DEBUG
@@ -123,34 +122,34 @@ public:
child processes: if the process is finished, the QProcess class may still be
there; furthermore a user can use QProcess to start more than one process.
The helper-class QProc has the semantics that one instance of this class maps
directly to a running child process.
*/
class QProc
{
public:
QProc( pid_t p, QProcess *proc=0 ) : pid(p), process(proc)
{
#if defined(QT_QPROCESS_DEBUG)
- qDebug( "QProc: Constructor for pid %d and QProcess %p", pid, process );
+ odebug << "QProc: Constructor for pid " << pid << " and QProcess " << process << "" << oendl;
#endif
socketStdin = 0;
socketStdout = 0;
socketStderr = 0;
}
~QProc()
{
#if defined(QT_QPROCESS_DEBUG)
- qDebug( "QProc: Destructor for pid %d and QProcess %p", pid, process );
+ odebug << "QProc: Destructor for pid " << pid << " and QProcess " << process << "" << oendl;
#endif
if ( process != 0 ) {
if ( process->d->notifierStdin )
process->d->notifierStdin->setEnabled( FALSE );
if ( process->d->notifierStdout )
process->d->notifierStdout->setEnabled( FALSE );
if ( process->d->notifierStderr )
process->d->notifierStderr->setEnabled( FALSE );
process->d->proc = 0;
}
if( socketStdin != 0 )
::close( socketStdin );
@@ -204,102 +203,102 @@ QProcessManager::QProcessManager()
{
procList = new QList<QProc>;
procList->setAutoDelete( TRUE );
// The SIGCHLD handler writes to a socket to tell the manager that
// something happened. This is done to get the processing in sync with the
// event reporting.
if ( ::socketpair( AF_UNIX, SOCK_STREAM, 0, sigchldFd ) ) {
sigchldFd[0] = 0;
sigchldFd[1] = 0;
} else {
#if defined(QT_QPROCESS_DEBUG)
- qDebug( "QProcessManager: install socket notifier (%d)", sigchldFd[1] );
+ odebug << "QProcessManager: install socket notifier (" << sigchldFd[1] << ")" << oendl;
#endif
QSocketNotifier *sn = new QSocketNotifier( sigchldFd[1],
QSocketNotifier::Read, this );
connect( sn, SIGNAL(activated(int)),
this, SLOT(sigchldHnd(int)) );
sn->setEnabled( TRUE );
}
// install a SIGCHLD handler and ignore SIGPIPE
struct sigaction act;
#if defined(QT_QPROCESS_DEBUG)
- qDebug( "QProcessManager: install a SIGCHLD handler" );
+ odebug << "QProcessManager: install a SIGCHLD handler" << oendl;
#endif
act.sa_handler = qt_C_sigchldHnd;
sigemptyset( &(act.sa_mask) );
sigaddset( &(act.sa_mask), SIGCHLD );
act.sa_flags = SA_NOCLDSTOP;
#if defined(SA_RESTART)
act.sa_flags |= SA_RESTART;
#endif
if ( sigaction( SIGCHLD, &act, &oldactChld ) != 0 )
- qWarning( "Error installing SIGCHLD handler" );
+ owarn << "Error installing SIGCHLD handler" << oendl;
#if defined(QT_QPROCESS_DEBUG)
- qDebug( "QProcessManager: install a SIGPIPE handler (SIG_IGN)" );
+ odebug << "QProcessManager: install a SIGPIPE handler (SIG_IGN)" << oendl;
#endif
/*
Using qt_C_sigpipeHnd rather than SIG_IGN is a workaround
for a strange problem where GNU tar (called by backuprestore)
would hang on filesystem-full. Strangely, the qt_C_sigpipeHnd
is never even called, yet this avoids the hang.
*/
act.sa_handler = qt_C_sigpipeHnd;
sigemptyset( &(act.sa_mask) );
sigaddset( &(act.sa_mask), SIGPIPE );
act.sa_flags = 0;
if ( sigaction( SIGPIPE, &act, &oldactPipe ) != 0 )
- qWarning( "Error installing SIGPIPE handler" );
+ owarn << "Error installing SIGPIPE handler" << oendl;
}
QProcessManager::~QProcessManager()
{
delete procList;
if ( sigchldFd[0] != 0 )
::close( sigchldFd[0] );
if ( sigchldFd[1] != 0 )
::close( sigchldFd[1] );
// restore SIGCHLD handler
#if defined(QT_QPROCESS_DEBUG)
- qDebug( "QProcessManager: restore old sigchild handler" );
+ odebug << "QProcessManager: restore old sigchild handler" << oendl;
#endif
if ( sigaction( SIGCHLD, &oldactChld, 0 ) != 0 )
- qWarning( "Error restoring SIGCHLD handler" );
+ owarn << "Error restoring SIGCHLD handler" << oendl;
#if defined(QT_QPROCESS_DEBUG)
- qDebug( "QProcessManager: restore old sigpipe handler" );
+ odebug << "QProcessManager: restore old sigpipe handler" << oendl;
#endif
if ( sigaction( SIGPIPE, &oldactPipe, 0 ) != 0 )
- qWarning( "Error restoring SIGPIPE handler" );
+ owarn << "Error restoring SIGPIPE handler" << oendl;
}
void QProcessManager::append( QProc *p )
{
procList->append( p );
#if defined(QT_QPROCESS_DEBUG)
- qDebug( "QProcessManager: append process (procList.count(): %d)", procList->count() );
+ odebug << "QProcessManager: append process (procList.count(): " << procList->count() << ")" << oendl;
#endif
}
void QProcessManager::remove( QProc *p )
{
procList->remove( p );
#if defined(QT_QPROCESS_DEBUG)
- qDebug( "QProcessManager: remove process (procList.count(): %d)", procList->count() );
+ odebug << "QProcessManager: remove process (procList.count(): " << procList->count() << ")" << oendl;
#endif
cleanup();
}
void QProcessManager::cleanup()
{
if ( procList->count() == 0 ) {
QTimer::singleShot( 0, this, SLOT(removeMe()) );
}
}
void QProcessManager::removeMe()
@@ -307,65 +306,65 @@ void QProcessManager::removeMe()
if ( procList->count() == 0 ) {
qprocess_cleanup_procmanager.remove( &QProcessPrivate::procManager );
QProcessPrivate::procManager = 0;
delete this;
}
}
void QProcessManager::sigchldHnd( int fd )
{
char tmp;
::read( fd, &tmp, sizeof(tmp) );
#if defined(QT_QPROCESS_DEBUG)
- qDebug( "QProcessManager::sigchldHnd()" );
+ odebug << "QProcessManager::sigchldHnd()" << oendl;
#endif
QProc *proc;
QProcess *process;
bool removeProc;
proc = procList->first();
while ( proc != 0 ) {
removeProc = FALSE;
process = proc->process;
QProcess *process_exit_notify=0;
if ( process != 0 ) {
if ( !process->isRunning() ) {
#if defined(QT_QPROCESS_DEBUG)
- qDebug( "QProcessManager::sigchldHnd() (PID: %d): process exited (QProcess available)", proc->pid );
+ odebug << "QProcessManager::sigchldHnd() (PID: " << proc->pid << "): process exited (QProcess available)" << oendl;
#endif
// read pending data
int nbytes = 0;
if ( ::ioctl(proc->socketStdout, FIONREAD, (char*)&nbytes)==0 && nbytes>0 ) {
#if defined(QT_QPROCESS_DEBUG)
- qDebug( "QProcessManager::sigchldHnd() (PID: %d): reading %d bytes of pending data on stdout", proc->pid, nbytes );
+ odebug << "QProcessManager::sigchldHnd() (PID: " << proc->pid << "): reading " << nbytes << " bytes of pending data on stdout" << oendl;
#endif
process->socketRead( proc->socketStdout );
}
nbytes = 0;
if ( ::ioctl(proc->socketStderr, FIONREAD, (char*)&nbytes)==0 && nbytes>0 ) {
#if defined(QT_QPROCESS_DEBUG)
- qDebug( "QProcessManager::sigchldHnd() (PID: %d): reading %d bytes of pending data on stderr", proc->pid, nbytes );
+ odebug << "QProcessManager::sigchldHnd() (PID: " << proc->pid << "): reading " << nbytes << " bytes of pending data on stderr" << oendl;
#endif
process->socketRead( proc->socketStderr );
}
if ( process->notifyOnExit )
process_exit_notify = process;
removeProc = TRUE;
}
} else {
int status;
if ( ::waitpid( proc->pid, &status, WNOHANG ) == proc->pid ) {
#if defined(QT_QPROCESS_DEBUG)
- qDebug( "QProcessManager::sigchldHnd() (PID: %d): process exited (QProcess not available)", proc->pid );
+ odebug << "QProcessManager::sigchldHnd() (PID: " << proc->pid << "): process exited (QProcess not available)" << oendl;
#endif
removeProc = TRUE;
}
}
if ( removeProc ) {
QProc *oldproc = proc;
proc = procList->next();
remove( oldproc );
} else {
proc = procList->next();
}
if ( process_exit_notify )
@@ -377,42 +376,42 @@ void QProcessManager::sigchldHnd( int fd )
/***********************************************************************
*
* QProcessPrivate
*
**********************************************************************/
QProcessManager *QProcessPrivate::procManager = 0;
QProcessPrivate::QProcessPrivate()
{
#if defined(QT_QPROCESS_DEBUG)
- qDebug( "QProcessPrivate: Constructor" );
+ odebug << "QProcessPrivate: Constructor" << oendl;
#endif
stdinBufRead = 0;
notifierStdin = 0;
notifierStdout = 0;
notifierStderr = 0;
exitValuesCalculated = FALSE;
socketReadCalled = FALSE;
proc = 0;
}
QProcessPrivate::~QProcessPrivate()
{
#if defined(QT_QPROCESS_DEBUG)
- qDebug( "QProcessPrivate: Destructor" );
+ odebug << "QProcessPrivate: Destructor" << oendl;
#endif
if ( proc != 0 ) {
if ( proc->socketStdin != 0 ) {
::close( proc->socketStdin );
proc->socketStdin = 0;
}
proc->process = 0;
}
while ( !stdinBuf.isEmpty() ) {
delete stdinBuf.dequeue();
@@ -590,25 +589,25 @@ QProcess::~QProcess()
You can call this function even when there already is a running
process in this object. In this case, QProcess closes standard input
of the old process and deletes pending data, i.e., you loose all
control over that process, but the process is not terminated. This applies
also if the process could not be started. (On operating systems that have
zombie processes, Qt will also wait() on the old process.)
\sa launch() closeStdin()
*/
bool QProcess::start( QStringList *env )
{
#if defined(QT_QPROCESS_DEBUG)
- qDebug( "QProcess::start()" );
+ odebug << "QProcess::start()" << oendl;
#endif
reset();
int sStdin[2];
int sStdout[2];
int sStderr[2];
// open sockets for piping
if ( (comms & Stdin) && ::socketpair( AF_UNIX, SOCK_STREAM, 0, sStdin ) == -1 ) {
return FALSE;
}
if ( (comms & Stderr) && ::socketpair( AF_UNIX, SOCK_STREAM, 0, sStderr ) == -1 ) {
@@ -626,25 +625,25 @@ bool QProcess::start( QStringList *env )
fd[0] = 0;
fd[1] = 0;
}
// construct the arguments for exec
QCString *arglistQ = new QCString[ _arguments.count() + 1 ];
const char** arglist = new const char*[ _arguments.count() + 1 ];
int i = 0;
for ( QStringList::Iterator it = _arguments.begin(); it != _arguments.end(); ++it ) {
arglistQ[i] = (*it).local8Bit();
arglist[i] = arglistQ[i];
#if defined(QT_QPROCESS_DEBUG)
- qDebug( "QProcess::start(): arg %d = %s", i, arglist[i] );
+ odebug << "QProcess::start(): arg " << i << " = " << arglist[i] << "" << oendl;
#endif
i++;
}
arglist[i] = 0;
// Must make sure signal handlers are installed before exec'ing
// in case the process exits quickly.
if ( d->procManager == 0 ) {
d->procManager = new QProcessManager;
qprocess_cleanup_procmanager.add( &d->procManager );
}
@@ -790,25 +789,25 @@ bool QProcess::start( QStringList *env )
this, SLOT(socketRead(int)) );
if ( ioRedirection )
d->notifierStderr->setEnabled( TRUE );
}
// cleanup and return
delete[] arglistQ;
delete[] arglist;
return TRUE;
error:
#if defined(QT_QPROCESS_DEBUG)
- qDebug( "QProcess::start(): error starting process" );
+ odebug << "QProcess::start(): error starting process" << oendl;
#endif
if ( d->procManager )
d->procManager->cleanup();
if ( comms & Stdin ) {
::close( sStdin[1] );
::close( sStdin[0] );
}
if ( comms & Stdout ) {
::close( sStdout[0] );
::close( sStdout[1] );
}
if ( comms & Stderr ) {
@@ -869,67 +868,67 @@ void QProcess::kill() const
::kill( d->proc->pid, SIGKILL );
}
/*!
Returns TRUE if the process is running, otherwise FALSE.
\sa normalExit() exitStatus() processExited()
*/
bool QProcess::isRunning() const
{
if ( d->exitValuesCalculated ) {
#if defined(QT_QPROCESS_DEBUG)
- qDebug( "QProcess::isRunning(): FALSE (already computed)" );
+ odebug << "QProcess::isRunning(): FALSE (already computed)" << oendl;
#endif
return FALSE;
}
if ( d->proc == 0 )
return FALSE;
int status;
if ( ::waitpid( d->proc->pid, &status, WNOHANG ) == d->proc->pid )
{
// compute the exit values
QProcess *that = (QProcess*)this; // mutable
that->exitNormal = WIFEXITED( status ) != 0;
if ( exitNormal ) {
that->exitStat = (char)WEXITSTATUS( status );
}
d->exitValuesCalculated = TRUE;
#if defined(QT_QPROCESS_DEBUG)
- qDebug( "QProcess::isRunning() (PID: %d): FALSE", d->proc->pid );
+ odebug << "QProcess::isRunning() (PID: " << d->proc->pid << "): FALSE" << oendl;
#endif
return FALSE;
}
#if defined(QT_QPROCESS_DEBUG)
- qDebug( "QProcess::isRunning() (PID: %d): TRUE", d->proc->pid );
+ odebug << "QProcess::isRunning() (PID: " << d->proc->pid << "): TRUE" << oendl;
#endif
return TRUE;
}
/*!
Writes the data \a buf to the standard input of the process. The process may
or may not read this data.
This function returns immediately; the QProcess class might write the data at
a later point (you have to enter the event loop for that). When all the data
is written to the process, the signal wroteToStdin() is emitted. This does
not mean that the process really read the data, since this class only detects
when it was able to write the data to the operating system.
\sa wroteToStdin() closeStdin() readStdout() readStderr()
*/
void QProcess::writeToStdin( const QByteArray& buf )
{
#if defined(QT_QPROCESS_DEBUG)
-// qDebug( "QProcess::writeToStdin(): write to stdin (%d)", d->socketStdin );
+// odebug << "QProcess::writeToStdin(): write to stdin (" << d->socketStdin << ")" << oendl;
#endif
d->stdinBuf.enqueue( new QByteArray(buf) );
if ( d->notifierStdin != 0 )
d->notifierStdin->setEnabled( TRUE );
}
/*!
Closes standard input of the process.
This function also deletes pending data that is not written to standard input
yet.
@@ -938,48 +937,48 @@ void QProcess::writeToStdin( const QByteArray& buf )
*/
void QProcess::closeStdin()
{
if ( d->proc == 0 )
return;
if ( d->proc->socketStdin !=0 ) {
while ( !d->stdinBuf.isEmpty() ) {
delete d->stdinBuf.dequeue();
}
delete d->notifierStdin;
d->notifierStdin = 0;
if ( ::close( d->proc->socketStdin ) != 0 ) {
- qWarning( "Could not close stdin of child process" );
+ owarn << "Could not close stdin of child process" << oendl;
}
#if defined(QT_QPROCESS_DEBUG)
- qDebug( "QProcess::closeStdin(): stdin (%d) closed", d->proc->socketStdin );
+ odebug << "QProcess::closeStdin(): stdin (" << d->proc->socketStdin << ") closed" << oendl;
#endif
d->proc->socketStdin = 0;
}
}
/*
This private slot is called when the process has outputted data to either
standard output or standard error.
*/
void QProcess::socketRead( int fd )
{
if ( d->socketReadCalled ) {
// the slots that are connected to the readyRead...() signals might
// trigger a recursive call of socketRead(). Avoid this since you get a
// blocking read otherwise.
return;
}
#if defined(QT_QPROCESS_DEBUG)
- qDebug( "QProcess::socketRead(): %d", fd );
+ odebug << "QProcess::socketRead(): " << fd << "" << oendl;
#endif
if ( fd == 0 )
return;
const int bufsize = 4096;
QByteArray *buffer = 0;
uint oldSize;
int n;
if ( fd == d->proc->socketStdout ) {
buffer = &d->bufStdout;
} else if ( fd == d->proc->socketStderr ) {
buffer = &d->bufStderr;
} else {
@@ -990,35 +989,35 @@ void QProcess::socketRead( int fd )
// read data
oldSize = buffer->size();
buffer->resize( oldSize + bufsize );
n = ::read( fd, buffer->data()+oldSize, bufsize );
if ( n > 0 )
buffer->resize( oldSize + n );
else
buffer->resize( oldSize );
// eof or error?
if ( n == 0 || n == -1 ) {
if ( fd == d->proc->socketStdout ) {
#if defined(QT_QPROCESS_DEBUG)
- qDebug( "QProcess::socketRead(): stdout (%d) closed", fd );
+ odebug << "QProcess::socketRead(): stdout (" << fd << ") closed" << oendl;
#endif
d->notifierStdout->setEnabled( FALSE );
delete d->notifierStdout;
d->notifierStdout = 0;
::close( d->proc->socketStdout );
d->proc->socketStdout = 0;
return;
} else if ( fd == d->proc->socketStderr ) {
#if defined(QT_QPROCESS_DEBUG)
- qDebug( "QProcess::socketRead(): stderr (%d) closed", fd );
+ odebug << "QProcess::socketRead(): stderr (" << fd << ") closed" << oendl;
#endif
d->notifierStderr->setEnabled( FALSE );
delete d->notifierStderr;
d->notifierStderr = 0;
::close( d->proc->socketStderr );
d->proc->socketStderr = 0;
return;
}
}
// read all data that is available
while ( n == bufsize ) {
oldSize = buffer->size();
@@ -1052,25 +1051,25 @@ void QProcess::socketRead( int fd )
This private slot is called when the process tries to read data from standard
input.
*/
void QProcess::socketWrite( int fd )
{
if ( fd != d->proc->socketStdin || d->proc->socketStdin == 0 )
return;
if ( d->stdinBuf.isEmpty() ) {
d->notifierStdin->setEnabled( FALSE );
return;
}
#if defined(QT_QPROCESS_DEBUG)
- qDebug( "QProcess::socketWrite(): write to stdin (%d)", fd );
+ odebug << "QProcess::socketWrite(): write to stdin (" << fd << ")" << oendl;
#endif
ssize_t ret = ::write( fd,
d->stdinBuf.head()->data() + d->stdinBufRead,
d->stdinBuf.head()->size() - d->stdinBufRead );
if ( ret > 0 )
d->stdinBufRead += ret;
if ( d->stdinBufRead == (ssize_t)d->stdinBuf.head()->size() ) {
d->stdinBufRead = 0;
delete d->stdinBuf.dequeue();
if ( wroteToStdinConnected && d->stdinBuf.isEmpty() )
emit wroteToStdin();
socketWrite( fd );