Пример #1
0
bool QSharedMemoryPrivate::attach(QSharedMemory::AccessMode mode)
{
    const QByteArray shmName = QFile::encodeName(makePlatformSafeKey(key));

    const int oflag = (mode == QSharedMemory::ReadOnly ? O_RDONLY : O_RDWR);
    const mode_t omode = (mode == QSharedMemory::ReadOnly ? 0400 : 0600);

#ifdef O_CLOEXEC
    // First try with O_CLOEXEC flag, if that fails, fall back to normal flags
    EINTR_LOOP(hand, ::shm_open(shmName.constData(), oflag | O_CLOEXEC, omode));
    if (hand == -1)
        EINTR_LOOP(hand, ::shm_open(shmName.constData(), oflag, omode));
#else
    EINTR_LOOP(hand, ::shm_open(shmName.constData(), oflag, omode));
#endif
    if (hand == -1) {
        const int errorNumber = errno;
        const QLatin1String function("QSharedMemory::attach (shm_open)");
        switch (errorNumber) {
        case ENAMETOOLONG:
        case EINVAL:
            errorString = QSharedMemory::tr("%1: bad name").arg(function);
            error = QSharedMemory::KeyError;
            break;
        default:
            setErrorString(function);
        }
        hand = -1;
        return false;
    }

    // grab the size
    QT_STATBUF st;
    if (QT_FSTAT(hand, &st) == -1) {
        setErrorString(QLatin1String("QSharedMemory::attach (fstat)"));
        cleanHandle();
        return false;
    }
    size = st.st_size;

    // grab the memory
    const int mprot = (mode == QSharedMemory::ReadOnly ? PROT_READ : PROT_READ | PROT_WRITE);
    memory = QT_MMAP(0, size, mprot, MAP_SHARED, hand, 0);
    if (memory == MAP_FAILED || !memory) {
        setErrorString(QLatin1String("QSharedMemory::attach (mmap)"));
        cleanHandle();
        memory = 0;
        size = 0;
        return false;
    }

#ifdef F_ADD_SEALS
    // Make sure the shared memory region will not shrink
    // otherwise someone could cause SIGBUS on us.
    // (see http://lwn.net/Articles/594919/)
    fcntl(hand, F_ADD_SEALS, F_SEAL_SHRINK);
#endif

    return true;
}
Пример #2
0
bool QWSSharedMemory::create(int size)
{
    if (shmId != -1)
        detach();

#ifndef QT_POSIX_IPC
    shmId = shmget(IPC_PRIVATE, size, IPC_CREAT | 0600);
#else
    // ### generate really unique IDs
    shmId = (getpid() << 16) + (localUniqueId.fetchAndAddRelaxed(1) % ushort(-1));
    QByteArray shmName = makeKey(shmId);
    EINTR_LOOP(hand, shm_open(shmName.constData(), O_RDWR | O_CREAT, 0660));
    if (hand != -1) {
        // the size may only be set once; ignore errors
        int ret;
        EINTR_LOOP(ret, ftruncate(hand, size));
        if (ret == -1)
            shmId = -1;
    } else {
        shmId = -1;
    }
#endif
    if (shmId == -1) {
#ifdef QT_SHM_DEBUG
        perror("QWSSharedMemory::create():");
        qWarning("Error allocating shared memory of size %d", size);
#endif
        detach();
        return false;
    }

#ifndef QT_POSIX_IPC
    shmBase = shmat(shmId, 0, 0);
    // On Linux, it is possible to attach a shared memory segment even if it
    // is already marked to be deleted. However, POSIX.1-2001 does not specify
    // this behaviour and many other implementations do not support it.
    shmctl(shmId, IPC_RMID, 0);
#else
    // grab the size
    QT_STATBUF st;
    if (QT_FSTAT(hand, &st) != -1) {
        shmSize = st.st_size;
        // grab the memory
        shmBase = mmap(0, shmSize, PROT_READ | PROT_WRITE, MAP_SHARED, hand, 0);
    }
#endif
    if (shmBase == (void*)-1 || !shmBase) {
#ifdef QT_SHM_DEBUG
        perror("QWSSharedMemory::create():");
        qWarning("Error attaching to shared memory id %d", shmId);
#endif
        detach();
        return false;
    }

    return true;
}
Пример #3
0
FUNCTION CODE c_getmsg
(
 struct PATH     *path,		/* In:  Path Control Block	  */
 GENPTR	    buffer,		/* Out: Buffer to store msg in    */
 COUNT	    *size		/* In:  Buffer size		  */
 )
    {
    GENPTR	bufptr;			/* extra buffer ptr to handle    */
					/*   split messages.		  */
    FUNINT  bufsiz;
    CODE   retcode = SUCCESS;		/* Return status		  */
    COUNT  len;				/* Length of msg read		  */
    struct sockaddr from;		/* Socket address of sender	  */
    socklen_t  fromlen;			/* Length of socket address	  */
    COUNT  snew;			/* Socket ID 			  */


    fromlen = sizeof (from);
    EINTR_LOOP(snew, accept ((*path).chnl, &from, &fromlen));
    if (snew < 0)
	{
	c_errtxt (path, errno);
	retcode = FAIL;
	}
    else
	{			/* Connection accepted, read message	*/
	bufptr = buffer;
	bufsiz = *size;
	do  
	    {  			/* until all of the message is in or error. */
#ifdef apollo
	    EINTR_LOOP(len, read (snew, bufptr, bufsiz));
#else
	    EINTR_LOOP(len, recv (snew, bufptr, bufsiz, 0));
#endif
            if (len <= 0) break;
	    bufptr += len;
	    bufsiz -= len;
	    }
	while (bufsiz > 0);
        close (snew);
	if (len < 0)
	    {
	    c_errtxt (path, errno);
	    retcode = FAIL;
	    }
	}
    return (retcode);
    }
Пример #4
0
void Process::dumpCore()
{
	int child = fork();

	switch (child) {
		case -1: // fork error
			fprintf(stderr, "Process.dumpCore: fork error: %s\n", strerror(errno));
			break;
		case 0: { // child
			abort();
			break;
		}
		default: { // parent
			int status = 0;
			EINTR_LOOP(::waitpid(child, &status, 0));
			char filename[80];
			time_t now = time(nullptr);
			struct tm tm;
			localtime_r(&now, &tm);
			strftime(filename, sizeof(filename), "%Y%m%d-%H%M%S.core", &tm);
			int rv = ::rename("core", filename);
			if (rv < 0) {
				fprintf(stderr, "Process.dumpCore: core rename error: %s\n", strerror(errno));
			} else {
				fprintf(stderr, "Process.dumpCore: %s\n", filename);
			}
		}
	}
}
Пример #5
0
Process::~Process()
{
	if (pid_ > 0)
		EINTR_LOOP(::waitpid(pid_, &status_, 0));

	//fprintf(stderr, "~Process(): rv=%d, errno=%s\n", rv, strerror(errno));
}
Пример #6
0
FUNCTION COUNT c_write 
(
 struct PATH *path,	/* in: path structure		        */
 FUNINT  fd,		/* in: file desc from c_accept		*/
 GENPTR	buffer,		/* in: buffer to receive next message	*/
 FUNINT size		/* in: buffer size			*/
 )
    {
    GENPTR	bufptr;			/* extra buffer ptr to handle    */
    COUNT	bufsiz;
    COUNT	len;			/* Length of msg read		  */
    COUNT	totalBytes = 0;	

    bufptr = buffer;
    bufsiz = size;
    do  			/* until all of the message is in or error. */
	{  			
	EINTR_LOOP(len, send (fd, bufptr, bufsiz, 0));
        if (len <= 0) break;
	bufptr += len;
	bufsiz -= len;
        totalBytes += len;
	}
    while (bufsiz > 0);

    if (len < 0)
	{
	c_errtxt (path, errno);
        return (0);
	}
    return (totalBytes);
    }
Пример #7
0
int qt_safe_select(int nfds, fd_set *fdread, fd_set *fdwrite, fd_set *fdexcept,
                   const struct timeval *orig_timeout)
{
    if (!orig_timeout) {
        // no timeout -> block forever
        register int ret;
        EINTR_LOOP(ret, select(nfds, fdread, fdwrite, fdexcept, 0));
        return ret;
    }

    timeval start = qt_gettime();
    timeval timeout = *orig_timeout;

    // loop and recalculate the timeout as needed
    int ret;
    forever {
        ret = ::select(nfds, fdread, fdwrite, fdexcept, &timeout);
        if (ret != -1 || errno != EINTR)
            return ret;

        // recalculate the timeout
        if (!time_update(&timeout, start, *orig_timeout)) {
            // timeout during update
            // or clock reset, fake timeout error
            return 0;
        }
    }
}
Пример #8
0
int qt_safe_select(int nfds, fd_set *fdread, fd_set *fdwrite, fd_set *fdexcept,
                   const struct timespec *orig_timeout)
{
    if (!orig_timeout) {
        // no timeout -> block forever
        int ret;
        EINTR_LOOP(ret, select(nfds, fdread, fdwrite, fdexcept, 0));
        return ret;
    }

    timespec start = qt_gettime();
    timespec timeout = *orig_timeout;

    // loop and recalculate the timeout as needed
    int ret;
    forever {
#ifndef Q_OS_QNX
        ret = ::pselect(nfds, fdread, fdwrite, fdexcept, &timeout, 0);
#else
        timeval timeoutVal;
        timeoutVal.tv_sec = timeout.tv_sec;
        timeoutVal.tv_usec = timeout.tv_nsec / 1000;
        ret = ::select(nfds, fdread, fdwrite, fdexcept, &timeoutVal);
#endif
        if (ret != -1 || errno != EINTR)
            return ret;

        // recalculate the timeout
        if (!time_update(&timeout, start, *orig_timeout)) {
            // timeout during update
            // or clock reset, fake timeout error
            return 0;
        }
    }
}
Пример #9
0
void QStorageInfoPrivate::retrieveVolumeInfo()
{
    QT_STATFSBUF statfs_buf;
    int result;
    EINTR_LOOP(result, QT_STATFS(QFile::encodeName(rootPath).constData(), &statfs_buf));
    if (result == 0) {
        valid = true;
        ready = true;

#if defined(Q_OS_BSD4) && !defined(Q_OS_NETBSD)
        bytesTotal = statfs_buf.f_blocks * statfs_buf.f_bsize;
        bytesFree = statfs_buf.f_bfree * statfs_buf.f_bsize;
        bytesAvailable = statfs_buf.f_bavail * statfs_buf.f_bsize;
#else
        bytesTotal = statfs_buf.f_blocks * statfs_buf.f_frsize;
        bytesFree = statfs_buf.f_bfree * statfs_buf.f_frsize;
        bytesAvailable = statfs_buf.f_bavail * statfs_buf.f_frsize;
#endif
        blockSize = statfs_buf.f_bsize;
#if defined(Q_OS_ANDROID) || defined (Q_OS_BSD4)
#if defined(_STATFS_F_FLAGS)
        readOnly = (statfs_buf.f_flags & ST_RDONLY) != 0;
#endif
#else
        readOnly = (statfs_buf.f_flag & ST_RDONLY) != 0;
#endif
    }
}
/*!
    \internal
 */
bool QSystemSemaphorePrivate::modifySemaphore(int count)
{
    if (-1 == handle())
        return false;

    struct sembuf operation;
    operation.sem_num = 0;
    operation.sem_op = count;
    operation.sem_flg = SEM_UNDO;

    int res;
    EINTR_LOOP(res, semop(semaphore, &operation, 1));
    if (-1 == res) {
        // If the semaphore was removed be nice and create it and then modifySemaphore again
        if (errno == EINVAL || errno == EIDRM) {
            semaphore = -1;
            cleanHandle();
            handle();
            return modifySemaphore(count);
        }
        setErrorString(QLatin1String("QSystemSemaphore::modifySemaphore"));
#if defined QSYSTEMSEMAPHORE_DEBUG
        qDebug() << QLatin1String("QSystemSemaphore::modify failed") << count << semctl(semaphore, 0, GETVAL) << errno << EIDRM << EINVAL;
#endif
        return false;
    }

    clearError();
    return true;
}
Пример #11
0
/*!
    \internal

    Behaves as close to POSIX poll(2) as practical but may be implemented
    using select(2) where necessary. In that case, returns -1 and sets errno
    to EINVAL if passed any descriptor greater than or equal to FD_SETSIZE.
*/
int qt_safe_poll(struct pollfd *fds, nfds_t nfds, const struct timespec *timeout_ts)
{
    if (!timeout_ts) {
        // no timeout -> block forever
        int ret;
        EINTR_LOOP(ret, qt_ppoll(fds, nfds, Q_NULLPTR));
        return ret;
    }

    timespec start = qt_gettime();
    timespec timeout = *timeout_ts;

    // loop and recalculate the timeout as needed
    forever {
        const int ret = qt_ppoll(fds, nfds, &timeout);
        if (ret != -1 || errno != EINTR)
            return ret;

        // recalculate the timeout
        if (!time_update(&timeout, start, *timeout_ts)) {
            // timeout during update
            // or clock reset, fake timeout error
            return 0;
        }
    }
}
Пример #12
0
void qt_nanosleep(timespec amount)
{
    // Mac doesn't have clock_nanosleep, but it does have nanosleep.
    // nanosleep is POSIX.1-1993

    int r;
    EINTR_LOOP(r, nanosleep(&amount, &amount));
}
Пример #13
0
bool QSharedMemoryPrivate::create(int size)
{
    if (!handle())
        return false;

    const QByteArray shmName = QFile::encodeName(makePlatformSafeKey(key));

    int fd;
#ifdef O_CLOEXEC
    // First try with O_CLOEXEC flag, if that fails, fall back to normal flags
    EINTR_LOOP(fd, ::shm_open(shmName.constData(), O_RDWR | O_CREAT | O_EXCL | O_CLOEXEC, 0600));
    if (fd == -1)
        EINTR_LOOP(fd, ::shm_open(shmName.constData(), O_RDWR | O_CREAT | O_EXCL, 0600));
#else
    EINTR_LOOP(fd, ::shm_open(shmName.constData(), O_RDWR | O_CREAT | O_EXCL, 0600));
#endif
    if (fd == -1) {
        const int errorNumber = errno;
        const QLatin1String function("QSharedMemory::attach (shm_open)");
        switch (errorNumber) {
        case ENAMETOOLONG:
        case EINVAL:
            errorString = QSharedMemory::tr("%1: bad name").arg(function);
            error = QSharedMemory::KeyError;
            break;
        default:
            setErrorString(function);
        }
        return false;
    }

    // the size may only be set once
    int ret;
    EINTR_LOOP(ret, QT_FTRUNCATE(fd, size));
    if (ret == -1) {
        setErrorString(QLatin1String("QSharedMemory::create (ftruncate)"));
        qt_safe_close(fd);
        return false;
    }

    qt_safe_close(fd);

    return true;
}
Пример #14
0
/*!
    Unlocks the semaphore. If other processes were blocking waiting to
    lock() the semaphore, one of them will wake up and succeed in
    locking.
*/
void QLock::unlock()
{
    if (!isValid())
        return;

    if (data->count > 0) {
        data->count--;
        if (!data->count) {
            int rv;
#if defined(QT_NO_SEMAPHORE)
            EINTR_LOOP(rv, flock(data->id, LOCK_UN));
#elif !defined(QT_POSIX_IPC)
            sembuf sops;
            sops.sem_num = 0;
            sops.sem_op = type == Write ? MAX_LOCKS : 1;
            sops.sem_flg = SEM_UNDO;

            EINTR_LOOP(rv, semop(data->id, &sops, 1));
#else
            if (type == Write) {
                sem_post(data->wsem);
                rv = sem_post(data->rsem);
            } else {
                EINTR_LOOP(rv, sem_wait(data->wsem));
                if (rv != -1) {
                    sem_post(data->id);
                    int semval;
                    sem_getvalue(data->id, &semval);
                    if (semval == MAX_LOCKS)
                        sem_post(data->rsem);
                    rv = sem_post(data->wsem);
                }
            }
#endif
            if (rv == -1)
                qDebug("QLock::unlock(): %s", strerror(errno));
        }
    } else {
        qDebug("QLock::unlock(): Unlock without corresponding lock");
    }
}
Пример #15
0
void qt_nanosleep(timespec amount)
{
    // We'd like to use clock_nanosleep.
    //
    // But clock_nanosleep is from POSIX.1-2001 and both are *not*
    // affected by clock changes when using relative sleeps, even for
    // CLOCK_REALTIME.
    //
    // nanosleep is POSIX.1-1993

    int r;
    EINTR_LOOP(r, nanosleep(&amount, &amount));
}
Пример #16
0
/*!
    Locks the semaphore with a lock of type \a t. Locks can either be
    \c Read or \c Write. If a lock is \c Read, attempts by other
    processes to obtain \c Read locks will succeed, and \c Write
    attempts will block until the lock is unlocked. If locked as \c
    Write, all attempts to lock by other processes will block until
    the lock is unlocked. Locks are stacked: i.e. a given QLock can be
    locked multiple times by the same process without blocking, and
    will only be unlocked after a corresponding number of unlock()
    calls.
*/
void QLock::lock(Type t)
{
    if (!isValid())
        return;

    if (!data->count) {
        type = t;

        int rv;
#if defined(QT_NO_SEMAPHORE)
        int op = type == Write ? LOCK_EX : LOCK_SH;

        EINTR_LOOP(rv, flock(data->id, op));
#elif !defined(QT_POSIX_IPC)
        sembuf sops;
        sops.sem_num = 0;
        sops.sem_op = type == Write ? -MAX_LOCKS : -1;
        sops.sem_flg = SEM_UNDO;

        EINTR_LOOP(rv, semop(data->id, &sops, 1));
#else
        if (type == Write) {
            EINTR_LOOP(rv, sem_wait(data->rsem));
            if (rv != -1) {
                EINTR_LOOP(rv, sem_wait(data->wsem));
                if (rv == -1)
                    sem_post(data->rsem);
            }
        } else {
            EINTR_LOOP(rv, sem_wait(data->wsem));
            if (rv != -1) {
                EINTR_LOOP(rv, sem_trywait(data->rsem));
                if (rv != -1 || errno == EAGAIN) {
                    EINTR_LOOP(rv, sem_wait(data->id));
                    if (rv == -1) {
                        int semval;
                        sem_getvalue(data->id, &semval);
                        if (semval == MAX_LOCKS)
                            sem_post(data->rsem);
                    }
                }
                rv = sem_post(data->wsem);
            }
        }
#endif
        if (rv == -1) {
            qDebug("QLock::lock(): %s", strerror(errno));
            return;
        }
    } else if (type == Read && t == Write) {
        qDebug("QLock::lock(): Attempt to lock for write while locked for read");
    }
    data->count++;
}
Пример #17
0
bool QWSLock::down(unsigned short semNum, int)
{
    int ret;

#ifndef QT_POSIX_IPC
    sembuf sops = { semNum, -1, 0 };
    // As the BackingStore lock is a mutex, and only one process may own
    // the lock, it's safe to use SEM_UNDO. On the other hand, the
    // Communication lock is locked by the client but unlocked by the
    // server and therefore can't use SEM_UNDO.
    if (semNum == BackingStore)
        sops.sem_flg |= SEM_UNDO;

    EINTR_LOOP(ret, semop(semId, &sops, 1));
#else
    EINTR_LOOP(ret, sem_wait(sems[semNum]));
#endif
    if (ret == -1) {
        qDebug("QWSLock::down(): %s", strerror(errno));
        return false;
    }

    return true;
}
Пример #18
0
void QEventDispatcherUNIX::wakeUp()
{
    Q_D(QEventDispatcherUNIX);
    if (d->wakeUps.testAndSetAcquire(0, 1)) {
#ifndef QT_NO_EVENTFD
        if (d->thread_pipe[1] == -1) {
            // eventfd
            eventfd_t value = 1;
            int ret;
            EINTR_LOOP(ret, eventfd_write(d->thread_pipe[0], value));
            return;
        }
#endif
        char c = 0;
        qt_safe_write( d->thread_pipe[1], &c, 1 );
    }
}
Пример #19
0
FUNCTION COUNT c_accept 
(
 struct PATH	*path		/* in: path name	*/
 )
    {
    struct sockaddr from;		/* Socket address of sender	  */
    socklen_t  fromlen;			/* Length of socket address	  */
    COUNT  socketFd;

    fromlen = sizeof (from);
    EINTR_LOOP(socketFd, accept ((*path).chnl, &from, &fromlen));
    if (socketFd < 0)
	{
	c_errtxt (path, errno);
        return (-1);
	}
    return (socketFd);
    }
Пример #20
0
/** tests whether child Process has exited already.
 */
bool Process::expired()
{
	if (pid_ <= 0)
		return true;

	int rv;
	EINTR_LOOP(rv = ::waitpid(pid_, &status_, WNOHANG));

	if (rv == 0)
		// child not exited yet
		return false;

	if (rv < 0)
		// error
		return false;

	pid_ = -1;
	return true;
}
Пример #21
0
FUNCTION  CODE  c_putmsg
(
 struct PATH *path,			/* In: Path Control Block	  */
 GENPTR	    buffer,		/* In: Message to be output	  */
 FUNINT	    size		/* In: Message size		  */
 )
    {
    CODE  retcode  =  SUCCESS;		/* Return status		  */
    CODE  status;			/* Local status code		  */


    EINTR_LOOP(status,send ( (*path).chnl, buffer, size, 0 ));
    if (status < 0)
	{
	c_errtxt (path, errno);
	retcode = FAIL;
	}
    return (retcode);
    }
Пример #22
0
QT_BEGIN_NAMESPACE

#define EINTR_LOOP(var, cmd)                    \
    do {                                        \
        var = cmd;                              \
    } while (var == -1 && errno == EINTR)

// don't call QT_OPEN or ::open
// call qt_safe_open
static inline int qt_safe_open(const char *pathname, int flags, mode_t mode = 0777)
{
#ifdef O_CLOEXEC
    flags |= O_CLOEXEC;
#endif
    int fd;
    EINTR_LOOP(fd, ::open(pathname, flags, mode));

    // unknown flags are ignored, so we have no way of verifying if
    // O_CLOEXEC was accepted
    if (fd != -1)
        ::fcntl(fd, F_SETFD, FD_CLOEXEC);
    return fd;
}
Пример #23
0
bool QWSSharedMemory::attach(int id)
{
    if (shmId == id)
        return id != -1;

    detach();

    if (id == -1)
        return false;

    shmId = id;
#ifndef QT_POSIX_IPC
    shmBase = shmat(shmId, 0, 0);
#else
    QByteArray shmName = makeKey(shmId);
    EINTR_LOOP(hand, shm_open(shmName.constData(), O_RDWR, 0660));
    if (hand != -1) {
        // grab the size
        QT_STATBUF st;
        if (QT_FSTAT(hand, &st) != -1) {
            shmSize = st.st_size;
            // grab the memory
            shmBase = mmap(0, shmSize, PROT_READ | PROT_WRITE, MAP_SHARED, hand, 0);
        }
    }
#endif
    if (shmBase == (void*)-1 || !shmBase) {
#ifdef QT_SHM_DEBUG
        perror("QWSSharedMemory::attach():");
        qWarning("Error attaching to shared memory id %d", shmId);
#endif
        detach();
        return false;
    }

    return true;
}
Пример #24
0
static inline qint64 qt_safe_write(int fd, const void *data, qint64 len)
{
    qint64 ret = 0;
    EINTR_LOOP(ret, ::write(fd, data, len));
    return ret;
}
Пример #25
0
void Process::setupChild(const std::string& _exe, const ArgumentList& _args, const Environment& _env, const std::string& _workdir)
{
	// restore signal handler(s)
	::signal(SIGPIPE, SIG_DFL);

	// setup environment
	int k = 0;
	std::vector<char *> env(_env.size() + 1);

	for (Environment::const_iterator i = _env.cbegin(), e = _env.cend(); i != e; ++i)
	{
		char *buf = new char[i->first.size() + i->second.size() + 2];
		::memcpy(buf, i->first.c_str(), i->first.size());
		buf[i->first.size()] = '=';
		::memcpy(buf + i->first.size() + 1, i->second.c_str(), i->second.size() + 1);

		//::fprintf(stderr, "proc[%d]: setting env[%d]: %s\n", getpid(), k, buf);
		//::fflush(stderr);
		env[k++] = buf;
	}
	env[_env.size()] = 0;

	// setup args
	std::vector<char *> args(_args.size() + 2);
	args[0] = const_cast<char *>(_exe.c_str());
	//::fprintf(stderr, "args[%d] = %s\n", 0, args[0]);
	for (int i = 0, e = _args.size(); i != e; ++i)
	{
		args[i + 1] = const_cast<char *>(_args[i].c_str());
		//::fprintf(stderr, "args[%d] = %s\n", i + 1, args[i + 1]);
	}
	args[args.size() - 1] = 0;

	// chdir
	if (!_workdir.empty())
	{
		::chdir(_workdir.c_str());
	}

	// setup I/O
	EINTR_LOOP(::close(STDIN_FILENO));
	EINTR_LOOP(::close(STDOUT_FILENO));
	EINTR_LOOP(::close(STDERR_FILENO));

	EINTR_LOOP(::dup2(input_.remote(), STDIN_FILENO));
	EINTR_LOOP(::dup2(output_.remote(), STDOUT_FILENO));
	EINTR_LOOP(::dup2(error_.remote(), STDERR_FILENO));

#if 0 // this is basically working but a very bad idea for high performance (XXX better get O_CLOEXEC working)
	for (int i = 3; i < 1024; ++i)
		::close(i);
#endif

//	input_.close();
//	output_.close();
//	error_.close();

	// finally execute
	::execve(args[0], &args[0], &env[0]);

	// OOPS
	::fprintf(stderr, "proc[%d]: execve(%s) error: %s\n", getpid(), args[0], strerror(errno));
	::fflush(stderr);
	::_exit(1);
}
Пример #26
0
/*!
    \internal
*/
bool QSystemSemaphorePrivate::modifySemaphore(int count)
{
#ifndef QT_POSIX_IPC
    if (-1 == handle())
        return false;

    struct sembuf operation;
    operation.sem_num = 0;
    operation.sem_op = count;
    operation.sem_flg = SEM_UNDO;

    register int res;
    EINTR_LOOP(res, semop(semaphore, &operation, 1));
    if (-1 == res) {
        // If the semaphore was removed be nice and create it and then modifySemaphore again
        if (errno == EINVAL || errno == EIDRM) {
            semaphore = -1;
            cleanHandle();
            handle();
            return modifySemaphore(count);
        }
        setErrorString(QLatin1String("QSystemSemaphore::modifySemaphore"));
#ifdef QSYSTEMSEMAPHORE_DEBUG
        qDebug() << QLatin1String("QSystemSemaphore::modify failed") << count << semctl(semaphore, 0, GETVAL) << errno << EIDRM << EINVAL;
#endif
        return false;
    }
#else
    if (!handle())
        return false;

    if (count > 0) {
        int cnt = count;
        do {
            if (sem_post(semaphore) == -1) {
                setErrorString(QLatin1String("QSystemSemaphore::modifySemaphore (sem_post)"));
#ifdef QSYSTEMSEMAPHORE_DEBUG
                qDebug() << QLatin1String("QSystemSemaphore::modify sem_post failed") << count << errno;
#endif
                // rollback changes to preserve the SysV semaphore behavior
                for ( ; cnt < count; ++cnt) {
                    register int res;
                    EINTR_LOOP(res, sem_wait(semaphore));
                }
                return false;
            }
            --cnt;
        } while (cnt > 0);
    } else {
        register int res;
        EINTR_LOOP(res, sem_wait(semaphore));
        if (res == -1) {
            // If the semaphore was removed be nice and create it and then modifySemaphore again
            if (errno == EINVAL || errno == EIDRM) {
                semaphore = SEM_FAILED;
                return modifySemaphore(count);
            }
            setErrorString(QLatin1String("QSystemSemaphore::modifySemaphore (sem_wait)"));
#ifdef QSYSTEMSEMAPHORE_DEBUG
            qDebug() << QLatin1String("QSystemSemaphore::modify sem_wait failed") << count << errno;
#endif
            return false;
        }
    }
#endif // QT_POSIX_IPC

    return true;
}