⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 qprocess_unix.cpp

📁 Trolltech公司发布的图形界面操作系统。可在qt-embedded-2.3.10平台上编译为嵌入式图形界面操作系统。
💻 CPP
📖 第 1 页 / 共 3 页
字号:
/************************************************************************ Copyright (C) 2000-2005 Trolltech AS.  All rights reserved.**** This file is part of the Qtopia Environment.** ** This program is free software; you can redistribute it and/or modify it** under the terms of the GNU General Public License as published by the** Free Software Foundation; either version 2 of the License, or (at your** option) any later version.** ** A copy of the GNU GPL license version 2 is included in this package as ** LICENSE.GPL.**** This program is distributed in the hope that it will be useful, but** WITHOUT ANY WARRANTY; without even the implied warranty of** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. ** See the GNU General Public License for more details.**** In addition, as a special exception Trolltech gives permission to link** the code of this program with Qtopia applications copyrighted, developed** and distributed by Trolltech under the terms of the Qtopia Personal Use** License Agreement. You must comply with the GNU General Public License** in all respects for all of the code used other than the applications** licensed under the Qtopia Personal Use License Agreement. If you modify** this file, you may extend this exception to your version of the file,** but you are not obligated to do so. If you do not wish to do so, delete** this exception statement from your version.** ** 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#include "qapplication.h"#include "qqueue.h"#include "qlist.h"#include "qsocketnotifier.h"#include "qtimer.h"#include "qregexp.h"#include "qcleanuphandler_p.h"#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 <errno.h>#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#ifdef Q_C_CALLBACKSextern "C" {#endif // Q_C_CALLBACKS#define QT_SIGNAL_RETTYPE       void#define QT_SIGNAL_ARGS          int#define QT_SIGNAL_IGNORE        SIG_IGN  QT_SIGNAL_RETTYPE qt_C_sigchldHnd(QT_SIGNAL_ARGS);  QT_SIGNAL_RETTYPE qt_C_sigpipeHnd(QT_SIGNAL_ARGS);#ifdef Q_C_CALLBACKS}#endif // Q_C_CALLBACKSclass QProc;class QProcessManager;class QProcessPrivate{public:    QProcessPrivate();    ~QProcessPrivate();    void closeOpenSocketsForChild();    void newProc( pid_t pid, QProcess *process );    QByteArray bufStdout;    QByteArray bufStderr;    QQueue<QByteArray> stdinBuf;    QSocketNotifier *notifierStdin;    QSocketNotifier *notifierStdout;    QSocketNotifier *notifierStderr;    ssize_t stdinBufRead;    QProc *proc;    bool exitValuesCalculated;    bool socketReadCalled;    static QProcessManager *procManager;};/*********************************************************************** * * QProc * **********************************************************************//*  The class QProcess does not necessarily map exactly to the running  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 );#endif	socketStdin = 0;	socketStdout = 0;	socketStderr = 0;    }    ~QProc()    {#if defined(QT_QPROCESS_DEBUG)	qDebug( "QProc: Destructor for pid %d and QProcess %p", pid, process );#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 );	// ### close these sockets even on parent exit or is it better only on	// sigchld (but what do I have to do with them on exit then)?	if( socketStdout != 0 )	    ::close( socketStdout );	if( socketStderr != 0 )	    ::close( socketStderr );    }    pid_t pid;    int socketStdin;    int socketStdout;    int socketStderr;    QProcess *process;};/*********************************************************************** * * QProcessManager * **********************************************************************/class QProcessManager : public QObject{    Q_OBJECTpublic:    QProcessManager();    ~QProcessManager();    void append( QProc *p );    void remove( QProc *p );    void cleanup();public slots:    void removeMe();    void sigchldHnd( int );public:    struct sigaction oldactChld;    struct sigaction oldactPipe;    QList<QProc> *procList;    int sigchldFd[2];};QCleanupHandler<QProcessManager> qprocess_cleanup_procmanager;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] );#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" );#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" );#if defined(QT_QPROCESS_DEBUG)    qDebug( "QProcessManager: install a SIGPIPE handler (SIG_IGN)" );#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" );}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" );#endif    if ( sigaction( SIGCHLD, &oldactChld, 0 ) != 0 )	qWarning( "Error restoring SIGCHLD handler" );#if defined(QT_QPROCESS_DEBUG)    qDebug( "QProcessManager: restore old sigpipe handler" );#endif    if ( sigaction( SIGPIPE, &oldactPipe, 0 ) != 0 )	qWarning( "Error restoring SIGPIPE handler" );}void QProcessManager::append( QProc *p ){    procList->append( p );#if defined(QT_QPROCESS_DEBUG)    qDebug( "QProcessManager: append process (procList.count(): %d)", procList->count() );#endif}void QProcessManager::remove( QProc *p ){    procList->remove( p );#if defined(QT_QPROCESS_DEBUG)    qDebug( "QProcessManager: remove process (procList.count(): %d)", procList->count() );#endif    cleanup();}void QProcessManager::cleanup(){    if ( procList->count() == 0 ) {	QTimer::singleShot( 0, this, SLOT(removeMe()) );    }}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()" );#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 );#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 );#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 );#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 );#endif		removeProc = TRUE;	    }	}	if ( removeProc ) {	    QProc *oldproc = proc;	    proc = procList->next();	    remove( oldproc );	} else {	    proc = procList->next();	}	if ( process_exit_notify )	    emit process_exit_notify->processExited();    }}#include "qprocess_unix.moc"/*********************************************************************** * * QProcessPrivate * **********************************************************************/QProcessManager *QProcessPrivate::procManager = 0;QProcessPrivate::QProcessPrivate(){#if defined(QT_QPROCESS_DEBUG)    qDebug( "QProcessPrivate: Constructor" );

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -