[Libreoffice-commits] .: sal/osl
Stephan Bergmann
sbergmann at kemper.freedesktop.org
Fri Dec 2 05:59:09 PST 2011
sal/osl/unx/createfilehandlefromfd.hxx | 45
sal/osl/unx/file.cxx | 8
sal/osl/unx/process.c | 1532 --------------------------------
sal/osl/unx/process.cxx | 1539 +++++++++++++++++++++++++++++++++
4 files changed, 1587 insertions(+), 1537 deletions(-)
New commits:
commit a84d912b7b6a55df59c3c7035c273e2219251d20
Author: Stephan Bergmann <sbergman at redhat.com>
Date: Fri Dec 2 14:54:00 2011 +0100
Improve ChildStatusProc diagnostics.
diff --git a/sal/osl/unx/createfilehandlefromfd.hxx b/sal/osl/unx/createfilehandlefromfd.hxx
new file mode 100644
index 0000000..116c074
--- /dev/null
+++ b/sal/osl/unx/createfilehandlefromfd.hxx
@@ -0,0 +1,45 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * Version: MPL 1.1 / GPLv3+ / LGPLv3+
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License or as specified alternatively below. You may obtain a copy of
+ * the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * Major Contributor(s):
+ * [ Copyright (C) 2011 Stephan Bergmann, Red Hat <sbergman at redhat.com> (initial
+ * developer) ]
+ *
+ * All Rights Reserved.
+ *
+ * For minor contributions see the git repository.
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 3 or later (the "GPLv3+"), or
+ * the GNU Lesser General Public License Version 3 or later (the "LGPLv3+"),
+ * in which case the provisions of the GPLv3+ or the LGPLv3+ are applicable
+ * instead of those above.
+ */
+
+#ifndef INCLUDED_SAL_OSL_UNX_CREATEFILEHANDLEFROMFD_HXX
+#define INCLUDED_SAL_OSL_UNX_CREATEFILEHANDLEFROMFD_HXX
+
+#include "sal/config.h"
+
+#include "osl/file.h"
+
+namespace osl { namespace detail {
+
+oslFileHandle createFileHandleFromFD(int fd); // defined in file.cxx
+
+} }
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sal/osl/unx/file.cxx b/sal/osl/unx/file.cxx
index 1bf76a8..f060413 100644
--- a/sal/osl/unx/file.cxx
+++ b/sal/osl/unx/file.cxx
@@ -33,6 +33,7 @@
#include "rtl/alloc.h"
#include "system.h"
+#include "createfilehandlefromfd.hxx"
#include "file_error_transl.h"
#include "file_url.h"
@@ -762,10 +763,7 @@ oslFileError FileHandle_Impl::syncFile()
return (result);
}
-/****************************************************************************
- * osl_createFileHandleFromFD
- ***************************************************************************/
-extern "C" oslFileHandle osl_createFileHandleFromFD( int fd )
+oslFileHandle osl::detail::createFileHandleFromFD( int fd )
{
if (-1 == fd)
return 0; // EINVAL
@@ -791,7 +789,7 @@ extern "C" oslFileHandle osl_createFileHandleFromFD( int fd )
pImpl->m_size = sal::static_int_cast< sal_uInt64 >(aFileStat.st_size);
}
- OSL_FILE_TRACE("osl_createFileHandleFromFD(%d, writeable) => %s",
+ OSL_FILE_TRACE("osl::detail::createFileHandleFromFD(%d, writeable) => %s",
pImpl->m_fd, rtl_string_getStr(pImpl->m_strFilePath));
return (oslFileHandle)(pImpl);
}
diff --git a/sal/osl/unx/process.c b/sal/osl/unx/process.c
deleted file mode 100644
index 4240567..0000000
--- a/sal/osl/unx/process.c
+++ /dev/null
@@ -1,1532 +0,0 @@
-/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
-/*************************************************************************
- *
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * Copyright 2000, 2010 Oracle and/or its affiliates.
- *
- * OpenOffice.org - a multi-platform office productivity suite
- *
- * This file is part of OpenOffice.org.
- *
- * OpenOffice.org is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License version 3
- * only, as published by the Free Software Foundation.
- *
- * OpenOffice.org 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 Lesser General Public License version 3 for more details
- * (a copy is included in the LICENSE file that accompanied this code).
- *
- * You should have received a copy of the GNU Lesser General Public License
- * version 3 along with OpenOffice.org. If not, see
- * <http://www.openoffice.org/license.html>
- * for a copy of the LGPLv3 License.
- *
- ************************************************************************/
-
-
-/*
- * ToDo:
- * - cleanup of process status things
- * - cleanup of process spawning
- * - cleanup of resource transfer
- */
-
-#if defined(SOLARIS)
- // The procfs may only be used without LFS in 32bits.
-# ifdef _FILE_OFFSET_BITS
-# undef _FILE_OFFSET_BITS
-# endif
-#endif
-
-
-#if defined(FREEBSD) || defined(NETBSD) || defined(DRAGONFLY)
-#include <machine/param.h>
-#endif
-
-#include "system.h"
-#if defined(SOLARIS)
-# include <sys/procfs.h>
-#endif
-#include <osl/diagnose.h>
-#include <osl/mutex.h>
-
-#ifndef _OSL_CONDITN_H_
-#include <osl/conditn.h>
-#endif
-#include <osl/thread.h>
-#include <osl/file.h>
-#include <osl/signal.h>
-#include <rtl/alloc.h>
-
-#include <grp.h>
-
-#include "procimpl.h"
-#include "readwrite_helper.h"
-#include "sockimpl.h"
-#include "secimpl.h"
-
-
-#define MAX_ARGS 255
-#define MAX_ENVS 255
-
-#if defined(MACOSX) || defined(IOS) || defined(IORESOURCE_TRANSFER_BSD) || defined(AIX)
-#define CONTROLLEN (sizeof(struct cmsghdr) + sizeof(int))
-#endif
-
-/* implemented in file.c */
-extern oslFileError FileURLToPath( char *, size_t, rtl_uString* );
-extern oslFileHandle osl_createFileHandleFromFD( int fd );
-
-/******************************************************************************
- *
- * Data Type Definition
- *
- ******************************************************************************/
-
-typedef struct {
- int m_hPipe;
- int m_hConn;
- sal_Char m_Name[PATH_MAX + 1];
-} Pipe;
-
-typedef struct {
- const sal_Char* m_pszArgs[MAX_ARGS + 1];
- oslProcessOption m_options;
- const sal_Char* m_pszDir;
- sal_Char* m_pszEnv[MAX_ENVS + 1];
- uid_t m_uid;
- gid_t m_gid;
- sal_Char* m_name;
- oslCondition m_started;
- oslProcessImpl* m_pProcImpl;
- oslFileHandle *m_pInputWrite;
- oslFileHandle *m_pOutputRead;
- oslFileHandle *m_pErrorRead;
-} ProcessData;
-
-typedef struct _oslPipeImpl {
- int m_Socket;
- sal_Char m_Name[PATH_MAX + 1];
-} oslPipeImpl;
-
-
-/******************************************************************************
- *
- * Function Declarations
- *
- *****************************************************************************/
-
-oslProcessError SAL_CALL osl_psz_executeProcess(sal_Char *pszImageName,
- sal_Char *pszArguments[],
- oslProcessOption Options,
- oslSecurity Security,
- sal_Char *pszDirectory,
- sal_Char *pszEnvironments[],
- oslProcess *pProcess,
- oslFileHandle *pInputWrite,
- oslFileHandle *pOutputRead,
- oslFileHandle *pErrorRead );
-
-
-oslProcessError SAL_CALL osl_searchPath_impl(
- const sal_Char* pszName,
- const sal_Char* pszPath,
- sal_Char Separator,
- sal_Char *pszBuffer,
- sal_uInt32 Max);
-
-
-sal_Bool osl_getFullPath(const sal_Char* pszFilename, sal_Char* pszPath, sal_uInt32 MaxLen);
-
-static oslProcessImpl* ChildList;
-static oslMutex ChildListMutex;
-
-/******************************************************************************
- Deprecated
- Old and buggy implementation of osl_searchPath used only by
- osl_psz_executeProcess.
- A new implemenation is in file_path_helper.cxx
- *****************************************************************************/
-
-oslProcessError SAL_CALL osl_searchPath_impl(const sal_Char* pszName, const sal_Char* pszPath,
- sal_Char Separator, sal_Char *pszBuffer, sal_uInt32 Max)
-{
- sal_Char path[PATH_MAX + 1];
- sal_Char *pchr;
-
- path[0] = '\0';
-
- OSL_ASSERT(pszName != NULL);
-
- if ( pszName == 0 )
- {
- return osl_Process_E_NotFound;
- }
-
- if (pszPath == NULL)
- pszPath = "PATH";
-
- if (Separator == '\0')
- Separator = ':';
-
-
- if ( (pchr = getenv(pszPath)) != 0 )
- {
- sal_Char *pstr;
-
- while (*pchr != '\0')
- {
- pstr = path;
-
- while ((*pchr != '\0') && (*pchr != Separator))
- *pstr++ = *pchr++;
-
- if ((pstr > path) && ((*(pstr - 1) != '/')))
- *pstr++ = '/';
-
- *pstr = '\0';
-
- strcat(path, pszName);
-
- if (access(path, 0) == 0)
- {
- char szRealPathBuf[PATH_MAX] = "";
-
- if( NULL == realpath(path, szRealPathBuf) || (strlen(szRealPathBuf) >= (sal_uInt32)Max))
- return osl_Process_E_Unknown;
-
- strcpy(pszBuffer, path);
-
- return osl_Process_E_None;
- }
-
- if (*pchr == Separator)
- pchr++;
- }
- }
-
- return osl_Process_E_NotFound;
-}
-
-/******************************************************************************
- *
- * New io resource transfer functions
- *
- *****************************************************************************/
-
-
-/**********************************************
- sendFdPipe
- *********************************************/
-
-static sal_Bool sendFdPipe(int PipeFD, int SocketFD)
-{
- sal_Bool bRet = sal_False;
-
- struct iovec iov[1];
- struct msghdr msg;
- char buf[2]; /* send_fd()/recv_fd() 2-byte protocol */
- int nSend;
- int RetCode=0;
-
-#if defined(IOCHANNEL_TRANSFER_BSD)
-
- OSL_TRACE("IOCHANNEL_TRANSFER_BSD send");
-/* OSL_TRACE("sending fd %i\n",SocketFD); */
-
- iov[0].iov_base = buf;
- iov[0].iov_len = sizeof(buf);
- msg.msg_iov = iov;
- msg.msg_iovlen = 1;
- msg.msg_name = NULL;
- msg.msg_namelen = 0;
-
- msg.msg_accrights = (caddr_t) &SocketFD; /* addr of descriptor */
- msg.msg_accrightslen = sizeof(int); /* pass 1 descriptor */
- buf[1] = 0; /* zero status means OK */
- buf[0] = 0; /* null byte flag to recv_fd() */
-
-#else
-
- struct cmsghdr* cmptr = (struct cmsghdr*)malloc(CONTROLLEN);
-
- OSL_TRACE("!!!!!! IOCHANNEL_TRANSFER_BSD_RENO send");
-/* OSL_TRACE("sending fd %i\n",SocketFD); */
-
- iov[0].iov_base = buf;
- iov[0].iov_len = sizeof(buf);
- msg.msg_iov = iov;
- msg.msg_iovlen = 1;
- msg.msg_name = NULL;
- msg.msg_namelen = 0;
- msg.msg_control = (caddr_t) cmptr;
- msg.msg_controllen = CONTROLLEN;
-
- cmptr->cmsg_level = SOL_SOCKET;
- cmptr->cmsg_type = SCM_RIGHTS;
- cmptr->cmsg_len = CONTROLLEN;
- memcpy(CMSG_DATA(cmptr), &SocketFD, sizeof(int));
-
-#endif
-
- if ( ( nSend = sendmsg(PipeFD, &msg, 0) ) > 0 )
- {
- bRet = sal_True;
- OSL_TRACE("sendFdPipe : send '%i' bytes",nSend);
-
- }
- else
- {
- OSL_TRACE("sendFdPipe : sending failed (%s)",strerror(errno));
- }
-
- bRet = safeRead(PipeFD, &RetCode, sizeof(RetCode));
-
- if ( bRet && RetCode == 1 )
- {
- OSL_TRACE("sendFdPipe : resource was received");
- }
- else
- {
- OSL_TRACE("sendFdPipe : resource wasn't received (error %s)", strerror(errno));
- }
-
-#if defined(IOCHANNEL_TRANSFER_BSD_RENO)
- free(cmptr);
-#endif
-
- return bRet;
-}
-
-/**********************************************
- receiveFdPipe
- *********************************************/
-
-static oslSocket receiveFdPipe(int PipeFD)
-{
- oslSocket pSocket = 0;
- struct msghdr msghdr;
- struct iovec iov[1];
- char buffer[2];
- sal_Int32 nRead;
- int newfd=-1;
- int nRetCode=0;
-/* char *ptr; */
-
-#if defined(IOCHANNEL_TRANSFER_BSD)
-
- OSL_TRACE("IOCHANNEL_TRANSFER_BSD receive");
-
- iov[0].iov_base = buffer;
- iov[0].iov_len = sizeof(buffer);
- msghdr.msg_name = NULL;
- msghdr.msg_namelen = 0;
- msghdr.msg_iov = iov;
- msghdr.msg_iovlen = 1;
- msghdr.msg_accrights = (caddr_t) &newfd; /* addr of descriptor */
- msghdr.msg_accrightslen = sizeof(int); /* receive 1 descriptor */
-
-#else
- struct cmsghdr* cmptr = (struct cmsghdr*)malloc(CONTROLLEN);
-
- OSL_TRACE(" !!!! IOCHANNEL_TRANSFER_BSD_RENO receive");
-
- iov[0].iov_base = buffer;
- iov[0].iov_len = sizeof(buffer);
- msghdr.msg_name = NULL;
- msghdr.msg_namelen = 0;
- msghdr.msg_iov = iov;
- msghdr.msg_iovlen = 1;
-
- msghdr.msg_control = (caddr_t) cmptr;
- msghdr.msg_controllen = CONTROLLEN;
-
-#endif
-
-
-#if defined(IOCHANNEL_TRANSFER_BSD)
-
- if ( ( nRead = recvmsg(PipeFD, &msghdr, 0) ) > 0 )
- {
- OSL_TRACE("receiveFdPipe : received '%i' bytes",nRead);
- }
-#else
-
- if ( ( ( nRead = recvmsg(PipeFD, &msghdr, 0) ) > 0 ) &&
- ( msghdr.msg_controllen == CONTROLLEN ) )
- {
- OSL_TRACE("receiveFdPipe : received '%i' bytes",nRead);
- memcpy(&newfd, CMSG_DATA(cmptr), sizeof(int));
- }
-#endif
- else
- {
- OSL_TRACE("receiveFdPipe : receiving failed (%s)",strerror(errno));
- }
-
- if ( newfd >= 0 )
- {
- pSocket = __osl_createSocketImpl(newfd);
- nRetCode=1;
- OSL_TRACE("received fd %i",newfd);
- }
-
- OSL_TRACE("receiveFdPipe : writing back %i",nRetCode);
- if ( !safeWrite(PipeFD, &nRetCode, sizeof(nRetCode)) )
- OSL_TRACE("write failed (%s)", strerror(errno));
-
- if ( nRead < 0 )
- {
- OSL_TRACE("write failed (%s)", strerror(errno));
- }
- else if ( nRead != sizeof(nRetCode) )
- {
- // TODO: Handle this case.
- OSL_TRACE("partial write: wrote %d out of %d)", nRead, sizeof(nRetCode));
- }
-
-#if defined(IOCHANNEL_TRANSFER_BSD_RENO)
- free(cmptr);
-#endif
-
- return pSocket;
-}
-
-/**********************************************
- osl_sendResourcePipe
- *********************************************/
-
-sal_Bool osl_sendResourcePipe(oslPipe pPipe, oslSocket pSocket)
-{
- sal_Bool bRet = sal_False;
-
- if ( pSocket == 0 || pPipe == 0 )
- {
- return sal_False;
- }
-
- bRet = sendFdPipe(pPipe->m_Socket,pSocket->m_Socket);
-
- return bRet;
-}
-
-/**********************************************
- osl_receiveResourcePipe
- *********************************************/
-
-oslSocket osl_receiveResourcePipe(oslPipe pPipe)
-{
- oslSocket pSocket=0;
-
- if ( pPipe == 0 )
- {
- return 0;
- }
-
- pSocket = receiveFdPipe(pPipe->m_Socket);
-
- return (oslSocket) pSocket;
-}
-
-
-
-/******************************************************************************
- *
- * Functions for starting a process
- *
- *****************************************************************************/
-
-static void ChildStatusProc(void *pData)
-{
- pid_t pid = -1;
- int status = 0;
- int channel[2];
- ProcessData data;
- ProcessData *pdata;
- int stdOutput[2] = { -1, -1 }, stdInput[2] = { -1, -1 }, stdError[2] = { -1, -1 };
-
- pdata = (ProcessData *)pData;
-
- /* make a copy of our data, because forking will only copy
- our local stack of the thread, so the process data will not be accessible
- in our child process */
- memcpy(&data, pData, sizeof(data));
-
-#ifdef NO_CHILD_PROCESSES
-#define fork() (errno = EINVAL, -1)
-#endif
- if (socketpair(AF_UNIX, SOCK_STREAM, 0, channel) == -1)
- status = errno;
-
- fcntl(channel[0], F_SETFD, FD_CLOEXEC);
- fcntl(channel[1], F_SETFD, FD_CLOEXEC);
-
- /* Create redirected IO pipes */
- if ( status == 0 && data.m_pInputWrite )
- if (pipe( stdInput ) == -1)
- status = errno;
-
- if ( status == 0 && data.m_pOutputRead )
- if (pipe( stdOutput ) == -1)
- status = errno;
-
- if ( status == 0 && data.m_pErrorRead )
- if (pipe( stdError ) == -1)
- status = errno;
-
- if ( (status == 0) && ((pid = fork()) == 0) )
- {
- /* Child */
- int chstatus = 0;
- int errno_copy;
-
- if (channel[0] != -1) close(channel[0]);
-
- if ((data.m_uid != (uid_t)-1) && ((data.m_uid != getuid()) || (data.m_gid != getgid())))
- {
- OSL_ASSERT(geteuid() == 0); /* must be root */
-
- if (! INIT_GROUPS(data.m_name, data.m_gid) || (setuid(data.m_uid) != 0))
- OSL_TRACE("Failed to change uid and guid, errno=%d (%s)", errno, strerror(errno));
-#if defined(LINUX) || defined (FREEBSD) || defined(NETBSD) || defined(OPENBSD) || defined(DRAGONFLY)
- unsetenv("HOME");
-#else
- putenv("HOME=");
-#endif
- }
-
- if (data.m_pszDir)
- chstatus = chdir(data.m_pszDir);
-
- if (chstatus == 0 && ((data.m_uid == (uid_t)-1) || ((data.m_uid == getuid()) && (data.m_gid == getgid()))))
- {
- int i;
- for (i = 0; data.m_pszEnv[i] != NULL; i++)
- {
- if (strchr(data.m_pszEnv[i], '=') == NULL)
- {
- unsetenv(data.m_pszEnv[i]); /*TODO: check error return*/
- }
- else
- {
- putenv(data.m_pszEnv[i]); /*TODO: check error return*/
- }
- }
-
- OSL_TRACE("ChildStatusProc : starting '%s'",data.m_pszArgs[0]);
-
- /* Connect std IO to pipe ends */
-
- /* Write end of stdInput not used in child process */
- if (stdInput[1] != -1) close( stdInput[1] );
-
- /* Read end of stdOutput not used in child process */
- if (stdOutput[0] != -1) close( stdOutput[0] );
-
- /* Read end of stdError not used in child process */
- if (stdError[0] != -1) close( stdError[0] );
-
- /* Redirect pipe ends to std IO */
-
- if ( stdInput[0] != STDIN_FILENO )
- {
- dup2( stdInput[0], STDIN_FILENO );
- if (stdInput[0] != -1) close( stdInput[0] );
- }
-
- if ( stdOutput[1] != STDOUT_FILENO )
- {
- dup2( stdOutput[1], STDOUT_FILENO );
- if (stdOutput[1] != -1) close( stdOutput[1] );
- }
-
- if ( stdError[1] != STDERR_FILENO )
- {
- dup2( stdError[1], STDERR_FILENO );
- if (stdError[1] != -1) close( stdError[1] );
- }
-
- // No need to check the return value of execv. If we return from
- // it, an error has occurred.
- execv(data.m_pszArgs[0], (sal_Char **)data.m_pszArgs);
- }
-
- OSL_TRACE("Failed to exec, errno=%d (%s)", errno, strerror(errno));
-
- OSL_TRACE("ChildStatusProc : starting '%s' failed",data.m_pszArgs[0]);
-
- /* if we reach here, something went wrong */
- errno_copy = errno;
- if ( !safeWrite(channel[1], &errno_copy, sizeof(errno_copy)) )
- OSL_TRACE("sendFdPipe : sending failed (%s)",strerror(errno));
-
- if ( channel[1] != -1 )
- close(channel[1]);
-
- _exit(255);
- }
- else
- { /* Parent */
- int i = -1;
- if (channel[1] != -1) close(channel[1]);
-
- /* Close unused pipe ends */
- if (stdInput[0] != -1) close( stdInput[0] );
- if (stdOutput[1] != -1) close( stdOutput[1] );
- if (stdError[1] != -1) close( stdError[1] );
-
- if (pid > 0)
- {
- while (((i = read(channel[0], &status, sizeof(status))) < 0))
- {
- if (errno != EINTR)
- break;
- }
- }
-
- if (channel[0] != -1) close(channel[0]);
-
- if ((pid > 0) && (i == 0))
- {
- pid_t child_pid;
- osl_acquireMutex(ChildListMutex);
-
- pdata->m_pProcImpl->m_pid = pid;
- pdata->m_pProcImpl->m_pnext = ChildList;
- ChildList = pdata->m_pProcImpl;
-
- /* Store used pipe ends in data structure */
-
- if ( pdata->m_pInputWrite )
- *(pdata->m_pInputWrite) = osl_createFileHandleFromFD( stdInput[1] );
-
- if ( pdata->m_pOutputRead )
- *(pdata->m_pOutputRead) = osl_createFileHandleFromFD( stdOutput[0] );
-
- if ( pdata->m_pErrorRead )
- *(pdata->m_pErrorRead) = osl_createFileHandleFromFD( stdError[0] );
-
- osl_releaseMutex(ChildListMutex);
-
- osl_setCondition(pdata->m_started);
-
- do
- {
- child_pid = waitpid(pid, &status, 0);
- } while ( 0 > child_pid && EINTR == errno );
-
- if ( child_pid < 0)
- {
- OSL_TRACE("Failed to wait for child process, errno=%d (%s)", errno, strerror(errno));
-
- /*
- We got an other error than EINTR. Anyway we have to wake up the
- waiting thread under any circumstances */
-
- child_pid = pid;
- }
-
-
- if ( child_pid > 0 )
- {
- oslProcessImpl* pChild;
-
- osl_acquireMutex(ChildListMutex);
-
- pChild = ChildList;
-
- /* check if it is one of our child processes */
- while (pChild != NULL)
- {
- if (pChild->m_pid == child_pid)
- {
- if (WIFEXITED(status))
- pChild->m_status = WEXITSTATUS(status);
- else if (WIFSIGNALED(status))
- pChild->m_status = 128 + WTERMSIG(status);
- else
- pChild->m_status = -1;
-
- osl_setCondition(pChild->m_terminated);
- }
-
- pChild = pChild->m_pnext;
- }
-
- osl_releaseMutex(ChildListMutex);
- }
- }
- else
- {
- OSL_TRACE("ChildStatusProc : starting '%s' failed",data.m_pszArgs[0]);
- OSL_TRACE("Failed to launch child process, child reports errno=%d (%s)", status, strerror(status));
-
- /* Close pipe ends */
- if ( pdata->m_pInputWrite )
- *pdata->m_pInputWrite = NULL;
-
- if ( pdata->m_pOutputRead )
- *pdata->m_pOutputRead = NULL;
-
- if ( pdata->m_pErrorRead )
- *pdata->m_pErrorRead = NULL;
-
- if (stdInput[1] != -1) close( stdInput[1] );
- if (stdOutput[0] != -1) close( stdOutput[0] );
- if (stdError[0] != -1) close( stdError[0] );
-
- //if pid > 0 then a process was created, even if it later failed
- //e.g. bash searching for a command to execute, and we still
- //need to clean it up to avoid "defunct" processes
- if (pid > 0)
- {
- pid_t child_pid;
- do
- {
- child_pid = waitpid(pid, &status, 0);
- } while ( 0 > child_pid && EINTR == errno );
- }
-
- /* notify (and unblock) parent thread */
- osl_setCondition(pdata->m_started);
- }
- }
-}
-
-/**********************************************
- osl_executeProcess_WithRedirectedIO
- *********************************************/
-
-oslProcessError SAL_CALL osl_executeProcess_WithRedirectedIO(
- rtl_uString *ustrImageName,
- rtl_uString *ustrArguments[],
- sal_uInt32 nArguments,
- oslProcessOption Options,
- oslSecurity Security,
- rtl_uString *ustrWorkDir,
- rtl_uString *ustrEnvironment[],
- sal_uInt32 nEnvironmentVars,
- oslProcess *pProcess,
- oslFileHandle *pInputWrite,
- oslFileHandle *pOutputRead,
- oslFileHandle *pErrorRead
- )
-{
-
- oslProcessError Error;
- sal_Char* pszWorkDir=0;
- sal_Char** pArguments=0;
- sal_Char** pEnvironment=0;
- unsigned int idx;
-
- char szImagePath[PATH_MAX] = "";
- char szWorkDir[PATH_MAX] = "";
-
- if ( ustrImageName && ustrImageName->length )
- {
- FileURLToPath( szImagePath, PATH_MAX, ustrImageName );
- }
-
- if ( ustrWorkDir != 0 && ustrWorkDir->length )
- {
- FileURLToPath( szWorkDir, PATH_MAX, ustrWorkDir );
- pszWorkDir = szWorkDir;
- }
-
- if ( pArguments == 0 && nArguments > 0 )
- {
- pArguments = (sal_Char**) malloc( ( nArguments + 2 ) * sizeof(sal_Char*) );
- }
-
-
- for ( idx = 0 ; idx < nArguments ; ++idx )
- {
- rtl_String* strArg =0;
-
-
- rtl_uString2String( &strArg,
- rtl_uString_getStr(ustrArguments[idx]),
- rtl_uString_getLength(ustrArguments[idx]),
- osl_getThreadTextEncoding(),
- OUSTRING_TO_OSTRING_CVTFLAGS );
-
- pArguments[idx]=strdup(rtl_string_getStr(strArg));
- rtl_string_release(strArg);
- pArguments[idx+1]=0;
- }
-
- for ( idx = 0 ; idx < nEnvironmentVars ; ++idx )
- {
- rtl_String* strEnv=0;
-
- if ( pEnvironment == 0 )
- {
- pEnvironment = (sal_Char**) malloc( ( nEnvironmentVars + 2 ) * sizeof(sal_Char*) );
- }
-
- rtl_uString2String( &strEnv,
- rtl_uString_getStr(ustrEnvironment[idx]),
- rtl_uString_getLength(ustrEnvironment[idx]),
- osl_getThreadTextEncoding(),
- OUSTRING_TO_OSTRING_CVTFLAGS );
-
- pEnvironment[idx]=strdup(rtl_string_getStr(strEnv));
- rtl_string_release(strEnv);
- pEnvironment[idx+1]=0;
- }
-
-
- Error = osl_psz_executeProcess(szImagePath,
- pArguments,
- Options,
- Security,
- pszWorkDir,
- pEnvironment,
- pProcess,
- pInputWrite,
- pOutputRead,
- pErrorRead
- );
-
- if ( pArguments != 0 )
- {
- for ( idx = 0 ; idx < nArguments ; ++idx )
- {
- if ( pArguments[idx] != 0 )
- {
- free(pArguments[idx]);
- }
- }
- free(pArguments);
- }
-
- if ( pEnvironment != 0 )
- {
- for ( idx = 0 ; idx < nEnvironmentVars ; ++idx )
- {
- if ( pEnvironment[idx] != 0 )
- {
- free(pEnvironment[idx]);
- }
- }
- free(pEnvironment);
- }
-
- return Error;
-}
-
-/**********************************************
- osl_executeProcess
- *********************************************/
-
-oslProcessError SAL_CALL osl_executeProcess(
- rtl_uString *ustrImageName,
- rtl_uString *ustrArguments[],
- sal_uInt32 nArguments,
- oslProcessOption Options,
- oslSecurity Security,
- rtl_uString *ustrWorkDir,
- rtl_uString *ustrEnvironment[],
- sal_uInt32 nEnvironmentVars,
- oslProcess *pProcess
- )
-{
- return osl_executeProcess_WithRedirectedIO(
- ustrImageName,
- ustrArguments,
- nArguments,
- Options,
- Security,
- ustrWorkDir,
- ustrEnvironment,
- nEnvironmentVars,
- pProcess,
- NULL,
- NULL,
- NULL
- );
-}
-
-/**********************************************
- osl_psz_executeProcess
- *********************************************/
-
-oslProcessError SAL_CALL osl_psz_executeProcess(sal_Char *pszImageName,
- sal_Char *pszArguments[],
- oslProcessOption Options,
- oslSecurity Security,
- sal_Char *pszDirectory,
- sal_Char *pszEnvironments[],
- oslProcess *pProcess,
- oslFileHandle *pInputWrite,
- oslFileHandle *pOutputRead,
- oslFileHandle *pErrorRead
- )
-{
- int i;
- sal_Char path[PATH_MAX + 1];
- ProcessData Data;
- oslThread hThread;
-
- path[0] = '\0';
-
- memset(&Data,0,sizeof(ProcessData));
- Data.m_pInputWrite = pInputWrite;
- Data.m_pOutputRead = pOutputRead;
- Data.m_pErrorRead = pErrorRead;
-
- if (pszImageName == NULL)
- pszImageName = pszArguments[0];
-
- OSL_ASSERT(pszImageName != NULL);
-
- if ( pszImageName == 0 )
- {
- return osl_Process_E_NotFound;
- }
-
- if ((Options & osl_Process_SEARCHPATH) &&
- (osl_searchPath_impl(pszImageName, NULL, '\0', path, sizeof(path)) == osl_Process_E_None))
- pszImageName = path;
-
- Data.m_pszArgs[0] = strdup(pszImageName);
- Data.m_pszArgs[1] = 0;
-
- if ( pszArguments != 0 )
- {
- for (i = 0; ((i + 2) < MAX_ARGS) && (pszArguments[i] != NULL); i++)
- Data.m_pszArgs[i+1] = strdup(pszArguments[i]);
- Data.m_pszArgs[i+2] = NULL;
- }
-
- Data.m_options = Options;
- Data.m_pszDir = (pszDirectory != NULL) ? strdup(pszDirectory) : NULL;
-
- if (pszEnvironments != NULL)
- {
- for (i = 0; ((i + 1) < MAX_ENVS) && (pszEnvironments[i] != NULL); i++)
- Data.m_pszEnv[i] = strdup(pszEnvironments[i]);
- Data.m_pszEnv[i+1] = NULL;
- }
- else
- Data.m_pszEnv[0] = NULL;
-
- if (Security != NULL)
- {
- Data.m_uid = ((oslSecurityImpl*)Security)->m_pPasswd.pw_uid;
- Data.m_gid = ((oslSecurityImpl*)Security)->m_pPasswd.pw_gid;
- Data.m_name = ((oslSecurityImpl*)Security)->m_pPasswd.pw_name;
- }
- else
- Data.m_uid = (uid_t)-1;
-
- Data.m_pProcImpl = (oslProcessImpl*) malloc(sizeof(oslProcessImpl));
- Data.m_pProcImpl->m_pid = 0;
- Data.m_pProcImpl->m_terminated = osl_createCondition();
- Data.m_pProcImpl->m_pnext = NULL;
-
- if (ChildListMutex == NULL)
- ChildListMutex = osl_createMutex();
-
- Data.m_started = osl_createCondition();
-
- hThread = osl_createThread(ChildStatusProc, &Data);
-
- osl_waitCondition(Data.m_started, NULL);
- osl_destroyCondition(Data.m_started);
-
- for (i = 0; Data.m_pszArgs[i] != NULL; i++)
- free((void *)Data.m_pszArgs[i]);
-
- for (i = 0; Data.m_pszEnv[i] != NULL; i++)
- free((void *)Data.m_pszEnv[i]);
-
- if ( Data.m_pszDir != 0 )
- {
- free((void *)Data.m_pszDir);
- }
-
- osl_destroyThread(hThread);
-
- if (Data.m_pProcImpl->m_pid != 0)
- {
- *pProcess = Data.m_pProcImpl;
-
- if (Options & osl_Process_WAIT)
- osl_joinProcess(*pProcess);
-
- return osl_Process_E_None;
- }
-
- osl_destroyCondition(Data.m_pProcImpl->m_terminated);
- free(Data.m_pProcImpl);
-
- return osl_Process_E_Unknown;
-}
-
-
-/******************************************************************************
- *
- * Functions for processes
- *
- *****************************************************************************/
-
-
-/**********************************************
- osl_terminateProcess
- *********************************************/
-
-oslProcessError SAL_CALL osl_terminateProcess(oslProcess Process)
-{
- if (Process == NULL)
- return osl_Process_E_Unknown;
-
- if (kill(((oslProcessImpl*)Process)->m_pid, SIGKILL) != 0)
- {
- switch (errno)
- {
- case EPERM:
- return osl_Process_E_NoPermission;
-
- case ESRCH:
- return osl_Process_E_NotFound;
-
- default:
- return osl_Process_E_Unknown;
- }
- }
-
- return osl_Process_E_None;
-}
-
-/**********************************************
- osl_getProcess
- *********************************************/
-
-oslProcess SAL_CALL osl_getProcess(oslProcessIdentifier Ident)
-{
- oslProcessImpl *pProcImpl;
-
- if (kill(Ident, 0) != -1)
- {
- oslProcessImpl* pChild;
-
- if (ChildListMutex == NULL)
- ChildListMutex = osl_createMutex();
-
- osl_acquireMutex(ChildListMutex);
-
- pChild = ChildList;
-
- /* check if it is one of our child processes */
- while (pChild != NULL)
- {
- if (Ident == (sal_uInt32) pChild->m_pid)
- break;
-
- pChild = pChild->m_pnext;
- }
-
- pProcImpl = (oslProcessImpl*) malloc(sizeof(oslProcessImpl));
- pProcImpl->m_pid = Ident;
- pProcImpl->m_terminated = osl_createCondition();
-
- if (pChild != NULL)
- {
- /* process is a child so insert into list */
- pProcImpl->m_pnext = pChild->m_pnext;
- pChild->m_pnext = pProcImpl;
-
- pProcImpl->m_status = pChild->m_status;
-
- if (osl_checkCondition(pChild->m_terminated))
- osl_setCondition(pProcImpl->m_terminated);
- }
- else
- pProcImpl->m_pnext = NULL;
-
- osl_releaseMutex(ChildListMutex);
- }
- else
- pProcImpl = NULL;
-
- return (pProcImpl);
-}
-
-/**********************************************
- osl_freeProcessHandle
- *********************************************/
-
-void SAL_CALL osl_freeProcessHandle(oslProcess Process)
-{
- if (Process != NULL)
- {
- oslProcessImpl *pChild, *pPrev = NULL;
-
- OSL_ASSERT(ChildListMutex != NULL);
-
- if ( ChildListMutex == 0 )
- {
- return;
- }
-
- osl_acquireMutex(ChildListMutex);
-
- pChild = ChildList;
-
- /* remove process from child list */
- while (pChild != NULL)
- {
- if (pChild == (oslProcessImpl*)Process)
- {
- if (pPrev != NULL)
- pPrev->m_pnext = pChild->m_pnext;
- else
- ChildList = pChild->m_pnext;
-
- break;
- }
-
- pPrev = pChild;
- pChild = pChild->m_pnext;
- }
-
- osl_releaseMutex(ChildListMutex);
-
- osl_destroyCondition(((oslProcessImpl*)Process)->m_terminated);
-
- free(Process);
- }
-}
-
-#if defined(LINUX)
-struct osl_procStat
-{
- /* from 'stat' */
- pid_t pid; /* pid */
- char command[16]; /* 'argv[0]' */ /* mfe: it all right char comm[16] in kernel! */
- char state; /* state (running, stopped, ...) */
- pid_t ppid; /* parent pid */
- pid_t pgrp; /* parent group */
- int session; /* session ID */
- int tty; /* no of tty */
- pid_t tpgid; /* group of process owning the tty */
- unsigned long flags; /* flags dunno */
- unsigned long minflt; /* minor page faults */
- unsigned long cminflt; /* minor page faults with children */
- unsigned long majflt; /* major page faults */
- unsigned long cmajflt; /* major page faults with children */
- unsigned long utime; /* no of jiffies in user mode */
- unsigned long stime; /* no of jiffies in kernel mode */
- unsigned long cutime; /* no of jiffies in user mode with children */
- unsigned long cstime; /* no of jiffies in kernel mode with children */
- unsigned long priority; /* nice value + 15 (kernel scheduling prio)*/
- long nice; /* nice value */
- long timeout; /* no of jiffies of next process timeout */
- long itrealvalue; /* no jiffies before next SIGALRM */
- unsigned long starttime; /* process started this no of jiffies after boot */
- unsigned long vsize; /* virtual memory size (in bytes) */
- long rss; /* resident set size (in pages) */
- unsigned long rss_rlim; /* rss limit (in bytes) */
- unsigned long startcode; /* address above program text can run */
- unsigned long endcode; /* address below program text can run */
- unsigned long startstack; /* address of start of stack */
- unsigned long kstkesp; /* current value of 'esp' (stack pointer) */
- unsigned long kstkeip; /* current value of 'eip' (instruction pointer) */
- /* mfe: Linux > 2.1.7x have more signals (88) */
-/*#ifdef LINUX */
- char signal[24]; /* pending signals */
- char blocked[24]; /* blocked signals */
- char sigignore[24]; /* ignored signals */
- char sigcatch[24]; /* catched signals */
-/*#else*/
-/* long long signal;*/
-/* long long blocked;*/
-/* long long sigignore;*/
-/* long long sigcatch;*/
-/*#endif */
- unsigned long wchan; /* 'channel' the process is waiting in */
- unsigned long nswap; /* ? */
- unsigned long cnswap; /* ? */
-
- /* from 'status' */
- int ruid; /* real uid */
- int euid; /* effective uid */
- int suid; /* saved uid */
- int fuid; /* file access uid */
- int rgid; /* real gid */
- int egid; /* effective gid */
- int sgid; /* saved gid */
- int fgid; /* file access gid */
- unsigned long vm_size; /* like vsize but on kb */
- unsigned long vm_lock; /* locked pages in kb */
- unsigned long vm_rss; /* like rss but in kb */
- unsigned long vm_data; /* data size */
- unsigned long vm_stack; /* stack size */
- unsigned long vm_exe; /* executable size */
- unsigned long vm_lib; /* library size */
-};
-
-/**********************************************
- osl_getProcStat
- *********************************************/
-
-sal_Bool osl_getProcStat(pid_t pid, struct osl_procStat* procstat)
-{
- int fd = 0;
- sal_Bool bRet = sal_False;
- char name[PATH_MAX + 1];
- snprintf(name, sizeof(name), "/proc/%u/stat", pid);
-
- if ((fd = open(name,O_RDONLY)) >=0 )
- {
- char* tmp=0;
- char prstatbuf[512];
- memset(prstatbuf,0,512);
- bRet = safeRead(fd, prstatbuf, 511);
-
- close(fd);
- /*printf("%s\n\n",prstatbuf);*/
-
- if (!bRet)
- return sal_False;
-
- tmp = strrchr(prstatbuf, ')');
- *tmp = '\0';
- memset(procstat->command, 0, sizeof(procstat->command));
-
- sscanf(prstatbuf, "%d (%15c", &procstat->pid, procstat->command);
- sscanf(tmp + 2,
- "%c"
- "%i %i %i %i %i"
- "%lu %lu %lu %lu %lu"
- "%lu %lu %lu %lu"
- "%lu %li %li %li"
- "%lu %lu %li %lu"
- "%lu %lu %lu %lu %lu"
- "%s %s %s %s"
- "%lu %lu %lu",
- &procstat->state,
- &procstat->ppid, &procstat->pgrp, &procstat->session, &procstat->tty, &procstat->tpgid,
- &procstat->flags, &procstat->minflt, &procstat->cminflt, &procstat->majflt, &procstat->cmajflt,
- &procstat->utime, &procstat->stime, &procstat->cutime, &procstat->cstime,
- &procstat->priority, &procstat->nice, &procstat->timeout, &procstat->itrealvalue,
- &procstat->starttime, &procstat->vsize, &procstat->rss, &procstat->rss_rlim,
- &procstat->startcode, &procstat->endcode, &procstat->startstack, &procstat->kstkesp, &procstat->kstkeip,
- procstat->signal, procstat->blocked, procstat->sigignore, procstat->sigcatch,
- &procstat->wchan, &procstat->nswap, &procstat->cnswap
- );
- }
- return bRet;
-}
-
-/**********************************************
- osl_getProcStatus
- *********************************************/
-
-sal_Bool osl_getProcStatus(pid_t pid, struct osl_procStat* procstat)
-{
- int fd = 0;
- char name[PATH_MAX + 1];
- sal_Bool bRet = sal_False;
-
- snprintf(name, sizeof(name), "/proc/%u/status", pid);
-
- if ((fd = open(name,O_RDONLY)) >=0 )
- {
- char* tmp=0;
- char prstatusbuf[512];
- memset(prstatusbuf,0,512);
- bRet = safeRead(fd, prstatusbuf, 511);
-
- close(fd);
-
- /* printf("\n\n%s\n\n",prstatusbuf);*/
-
- if (!bRet)
- return sal_False;
-
- tmp = strstr(prstatusbuf,"Uid:");
- if(tmp)
- {
- sscanf(tmp,"Uid:\t%d\t%d\t%d\t%d",
- &procstat->ruid, &procstat->euid, &procstat->suid, &procstat->fuid
- );
- }
-
-
- tmp = strstr(prstatusbuf,"Gid:");
- if(tmp)
- {
- sscanf(tmp,"Gid:\t%d\t%d\t%d\t%d",
- &procstat->rgid, &procstat->egid, &procstat->sgid, &procstat->fgid
- );
- }
-
- tmp = strstr(prstatusbuf,"VmSize:");
- if(tmp)
- {
- sscanf(tmp,
- "VmSize: %lu kB\n"
- "VmLck: %lu kB\n"
- "VmRSS: %lu kB\n"
- "VmData: %lu kB\n"
- "VmStk: %lu kB\n"
- "VmExe: %lu kB\n"
- "VmLib: %lu kB\n",
- &procstat->vm_size, &procstat->vm_lock, &procstat->vm_rss, &procstat->vm_data,
- &procstat->vm_stack, &procstat->vm_exe, &procstat->vm_lib
- );
- }
-
- tmp = strstr(prstatusbuf,"SigPnd:");
- if(tmp)
- {
- sscanf(tmp, "SigPnd: %s SigBlk: %s SigIgn: %s %*s %s",
- procstat->signal, procstat->blocked, procstat->sigignore, procstat->sigcatch
- );
- }
- }
- return bRet;
-}
-
-#endif
-
-/**********************************************
- osl_getProcessInfo
- *********************************************/
-
-oslProcessError SAL_CALL osl_getProcessInfo(oslProcess Process, oslProcessData Fields, oslProcessInfo* pInfo)
-{
- pid_t pid;
-
- if (Process == NULL)
- pid = getpid();
- else
- pid = ((oslProcessImpl*)Process)->m_pid;
-
- if (! pInfo || (pInfo->Size != sizeof(oslProcessInfo)))
- return osl_Process_E_Unknown;
-
- pInfo->Fields = 0;
-
- if (Fields & osl_Process_IDENTIFIER)
- {
- pInfo->Ident = pid;
- pInfo->Fields |= osl_Process_IDENTIFIER;
- }
-
- if (Fields & osl_Process_EXITCODE)
- {
- if ((Process != NULL) &&
- osl_checkCondition(((oslProcessImpl*)Process)->m_terminated))
- {
- pInfo->Code = ((oslProcessImpl*)Process)->m_status;
- pInfo->Fields |= osl_Process_EXITCODE;
- }
- }
-
- if (Fields & (osl_Process_HEAPUSAGE | osl_Process_CPUTIMES))
- {
-
-#if defined(SOLARIS)
-
- int fd;
- sal_Char name[PATH_MAX + 1];
-
- snprintf(name, sizeof(name), "/proc/%u", pid);
-
- if ((fd = open(name, O_RDONLY)) >= 0)
- {
- prstatus_t prstatus;
-
- if (ioctl(fd, PIOCSTATUS, &prstatus) >= 0)
- {
- if (Fields & osl_Process_CPUTIMES)
- {
- pInfo->UserTime.Seconds = prstatus.pr_utime.tv_sec;
- pInfo->UserTime.Nanosec = prstatus.pr_utime.tv_nsec;
- pInfo->SystemTime.Seconds = prstatus.pr_stime.tv_sec;
- pInfo->SystemTime.Nanosec = prstatus.pr_stime.tv_nsec;
-
- pInfo->Fields |= osl_Process_CPUTIMES;
- }
-
- if (Fields & osl_Process_HEAPUSAGE)
- {
- pInfo->HeapUsage = prstatus.pr_brksize;
-
- pInfo->Fields |= osl_Process_HEAPUSAGE;
- }
-
- close(fd);
-
- return (pInfo->Fields == Fields) ? osl_Process_E_None : osl_Process_E_Unknown;
- }
- else
- close(fd);
- }
-
-#elif defined(LINUX)
-
- if ( (Fields & osl_Process_CPUTIMES) || (Fields & osl_Process_HEAPUSAGE) )
- {
- struct osl_procStat procstat;
- memset(&procstat,0,sizeof(procstat));
-
- if ( (Fields & osl_Process_CPUTIMES) && osl_getProcStat(pid, &procstat) )
- {
- /*
- * mfe:
- * We calculate only time of the process proper.
- * Threads are processes, we do not consider their time here!
- * (For this, cutime and cstime should be used, it seems not
- * to work in 2.0.36)
- */
-
- long clktck;
- unsigned long hz;
- unsigned long userseconds;
- unsigned long systemseconds;
-
- clktck = sysconf(_SC_CLK_TCK);
- if (clktck < 0) {
- return osl_Process_E_Unknown;
- }
- hz = (unsigned long) clktck;
-
- userseconds = procstat.utime/hz;
- systemseconds = procstat.stime/hz;
-
- pInfo->UserTime.Seconds = userseconds;
- pInfo->UserTime.Nanosec = procstat.utime - (userseconds * hz);
- pInfo->SystemTime.Seconds = systemseconds;
- pInfo->SystemTime.Nanosec = procstat.stime - (systemseconds * hz);
-
- pInfo->Fields |= osl_Process_CPUTIMES;
- }
-
- if ( (Fields & osl_Process_HEAPUSAGE) && osl_getProcStatus(pid, &procstat) )
- {
- /*
- * mfe:
- * vm_data (found in status) shows the size of the data segment
- * it a rough approximation of the core heap size
- */
- pInfo->HeapUsage = procstat.vm_data*1024;
-
- pInfo->Fields |= osl_Process_HEAPUSAGE;
- }
- }
-
- return (pInfo->Fields == Fields) ? osl_Process_E_None : osl_Process_E_Unknown;
-#endif
-
- }
-
- return (pInfo->Fields == Fields) ? osl_Process_E_None : osl_Process_E_Unknown;
-}
-
-
-/***********************************************
- helper function for osl_joinProcessWithTimeout
- **********************************************/
-
-static int is_timeout(const struct timeval* tend)
-{
- struct timeval tcurrent;
- gettimeofday(&tcurrent, NULL);
- return (tcurrent.tv_sec >= tend->tv_sec);
-}
-
-/**********************************************
- kill(pid, 0) is usefull for checking if a
- process is still alive, but remember that
- kill even returns 0 if the process is already
- a zombie.
- *********************************************/
-
-static int is_process_dead(pid_t pid)
-{
- return ((-1 == kill(pid, 0)) && (ESRCH == errno));
-}
-
-/**********************************************
- osl_joinProcessWithTimeout
- *********************************************/
-
-oslProcessError SAL_CALL osl_joinProcessWithTimeout(oslProcess Process, const TimeValue* pTimeout)
-{
- oslProcessImpl* pChild = ChildList;
- oslProcessError osl_error = osl_Process_E_None;
-
- OSL_PRECOND(Process, "osl_joinProcess: Invalid parameter");
- OSL_ASSERT(ChildListMutex);
-
- if (NULL == Process || 0 == ChildListMutex)
- return osl_Process_E_Unknown;
-
- osl_acquireMutex(ChildListMutex);
-
- /* check if process is a child of ours */
- while (pChild != NULL)
- {
- if (pChild == (oslProcessImpl*)Process)
- break;
-
- pChild = pChild->m_pnext;
- }
-
- osl_releaseMutex(ChildListMutex);
-
- if (pChild != NULL)
- {
- oslConditionResult cond_res = osl_waitCondition(pChild->m_terminated, pTimeout);
-
- if (osl_cond_result_timeout == cond_res)
- osl_error = osl_Process_E_TimedOut;
- else if (osl_cond_result_ok != cond_res)
- osl_error = osl_Process_E_Unknown;
- }
- else /* alien process; StatusThread will not be able
- to set the condition terminated */
- {
- pid_t pid = ((oslProcessImpl*)Process)->m_pid;
-
- if (pTimeout)
- {
- int timeout = 0;
- struct timeval tend;
-
- gettimeofday(&tend, NULL);
-
- tend.tv_sec += pTimeout->Seconds;
-
- while (!is_process_dead(pid) && ((timeout = is_timeout(&tend)) == 0))
- sleep(1);
-
- if (timeout)
- osl_error = osl_Process_E_TimedOut;
- }
- else /* infinite */
- {
- while (!is_process_dead(pid))
- sleep(1);
- }
- }
- return osl_error;
-}
-
-/**********************************************
- osl_joinProcess
- *********************************************/
-
-oslProcessError SAL_CALL osl_joinProcess(oslProcess Process)
-{
- return osl_joinProcessWithTimeout(Process, NULL);
-}
-
-/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sal/osl/unx/process.cxx b/sal/osl/unx/process.cxx
new file mode 100644
index 0000000..c35a340
--- /dev/null
+++ b/sal/osl/unx/process.cxx
@@ -0,0 +1,1539 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#include "sal/config.h"
+
+#include <cassert>
+
+/*
+ * ToDo:
+ * - cleanup of process status things
+ * - cleanup of process spawning
+ * - cleanup of resource transfer
+ */
+
+#if defined(SOLARIS)
+ // The procfs may only be used without LFS in 32bits.
+# ifdef _FILE_OFFSET_BITS
+# undef _FILE_OFFSET_BITS
+# endif
+#endif
+
+
+#if defined(FREEBSD) || defined(NETBSD) || defined(DRAGONFLY)
+#include <machine/param.h>
+#endif
+
+#include "system.h"
+#if defined(SOLARIS)
+# include <sys/procfs.h>
+#endif
+#include <osl/diagnose.h>
+#include <osl/mutex.h>
+
+#ifndef _OSL_CONDITN_H_
+#include <osl/conditn.h>
+#endif
+#include <osl/thread.h>
+#include <osl/file.h>
+#include <osl/signal.h>
+#include <rtl/alloc.h>
+#include <sal/log.hxx>
+
+#include <grp.h>
+
+#include "createfilehandlefromfd.hxx"
+#include "file_url.h"
+#include "procimpl.h"
+#include "readwrite_helper.h"
+#include "sockimpl.h"
+#include "secimpl.h"
+
+#define MAX_ARGS 255
+#define MAX_ENVS 255
+
+#if defined(MACOSX) || defined(IOS) || defined(IORESOURCE_TRANSFER_BSD) || defined(AIX)
+#define CONTROLLEN (sizeof(struct cmsghdr) + sizeof(int))
+#endif
+
+/******************************************************************************
+ *
+ * Data Type Definition
+ *
+ ******************************************************************************/
+
+typedef struct {
+ int m_hPipe;
+ int m_hConn;
+ sal_Char m_Name[PATH_MAX + 1];
+} Pipe;
+
+typedef struct {
+ const sal_Char* m_pszArgs[MAX_ARGS + 1];
+ oslProcessOption m_options;
+ const sal_Char* m_pszDir;
+ sal_Char* m_pszEnv[MAX_ENVS + 1];
+ uid_t m_uid;
+ gid_t m_gid;
+ sal_Char* m_name;
+ oslCondition m_started;
+ oslProcessImpl* m_pProcImpl;
+ oslFileHandle *m_pInputWrite;
+ oslFileHandle *m_pOutputRead;
+ oslFileHandle *m_pErrorRead;
+} ProcessData;
+
+/******************************************************************************
+ *
+ * Function Declarations
+ *
+ *****************************************************************************/
+
+oslProcessError SAL_CALL osl_psz_executeProcess(sal_Char *pszImageName,
+ sal_Char *pszArguments[],
+ oslProcessOption Options,
+ oslSecurity Security,
+ sal_Char *pszDirectory,
+ sal_Char *pszEnvironments[],
+ oslProcess *pProcess,
+ oslFileHandle *pInputWrite,
+ oslFileHandle *pOutputRead,
+ oslFileHandle *pErrorRead );
+
+
+oslProcessError SAL_CALL osl_searchPath_impl(
+ const sal_Char* pszName,
+ const sal_Char* pszPath,
+ sal_Char Separator,
+ sal_Char *pszBuffer,
+ sal_uInt32 Max);
+
+
+sal_Bool osl_getFullPath(const sal_Char* pszFilename, sal_Char* pszPath, sal_uInt32 MaxLen);
+
+static oslProcessImpl* ChildList;
+static oslMutex ChildListMutex;
+
+/******************************************************************************
+ Deprecated
+ Old and buggy implementation of osl_searchPath used only by
+ osl_psz_executeProcess.
+ A new implemenation is in file_path_helper.cxx
+ *****************************************************************************/
+
+oslProcessError SAL_CALL osl_searchPath_impl(const sal_Char* pszName, const sal_Char* pszPath,
+ sal_Char Separator, sal_Char *pszBuffer, sal_uInt32 Max)
+{
+ sal_Char path[PATH_MAX + 1];
+ sal_Char *pchr;
+
+ path[0] = '\0';
+
+ OSL_ASSERT(pszName != NULL);
+
+ if ( pszName == 0 )
+ {
+ return osl_Process_E_NotFound;
+ }
+
+ if (pszPath == NULL)
+ pszPath = "PATH";
+
+ if (Separator == '\0')
+ Separator = ':';
+
+
+ if ( (pchr = getenv(pszPath)) != 0 )
+ {
+ sal_Char *pstr;
+
+ while (*pchr != '\0')
+ {
+ pstr = path;
+
+ while ((*pchr != '\0') && (*pchr != Separator))
+ *pstr++ = *pchr++;
+
+ if ((pstr > path) && ((*(pstr - 1) != '/')))
+ *pstr++ = '/';
+
+ *pstr = '\0';
+
+ strcat(path, pszName);
+
+ if (access(path, 0) == 0)
+ {
+ char szRealPathBuf[PATH_MAX] = "";
+
+ if( NULL == realpath(path, szRealPathBuf) || (strlen(szRealPathBuf) >= (sal_uInt32)Max))
+ return osl_Process_E_Unknown;
+
+ strcpy(pszBuffer, path);
+
+ return osl_Process_E_None;
+ }
+
+ if (*pchr == Separator)
+ pchr++;
+ }
+ }
+
+ return osl_Process_E_NotFound;
+}
+
+/******************************************************************************
+ *
+ * New io resource transfer functions
+ *
+ *****************************************************************************/
+
+
+/**********************************************
+ sendFdPipe
+ *********************************************/
+
+static sal_Bool sendFdPipe(int PipeFD, int SocketFD)
+{
+ sal_Bool bRet = sal_False;
+
+ struct iovec iov[1];
+ struct msghdr msg;
+ char buf[2]; /* send_fd()/recv_fd() 2-byte protocol */
+ int nSend;
+ int RetCode=0;
+
+#if defined(IOCHANNEL_TRANSFER_BSD)
+
+ OSL_TRACE("IOCHANNEL_TRANSFER_BSD send");
+/* OSL_TRACE("sending fd %i\n",SocketFD); */
+
+ iov[0].iov_base = buf;
+ iov[0].iov_len = sizeof(buf);
+ msg.msg_iov = iov;
+ msg.msg_iovlen = 1;
+ msg.msg_name = NULL;
+ msg.msg_namelen = 0;
+
+ msg.msg_accrights = (caddr_t) &SocketFD; /* addr of descriptor */
+ msg.msg_accrightslen = sizeof(int); /* pass 1 descriptor */
+ buf[1] = 0; /* zero status means OK */
+ buf[0] = 0; /* null byte flag to recv_fd() */
+
+#else
+
+ struct cmsghdr* cmptr = (struct cmsghdr*)malloc(CONTROLLEN);
+
+ OSL_TRACE("!!!!!! IOCHANNEL_TRANSFER_BSD_RENO send");
+/* OSL_TRACE("sending fd %i\n",SocketFD); */
+
+ iov[0].iov_base = buf;
+ iov[0].iov_len = sizeof(buf);
+ msg.msg_iov = iov;
+ msg.msg_iovlen = 1;
+ msg.msg_name = NULL;
+ msg.msg_namelen = 0;
+ msg.msg_control = (caddr_t) cmptr;
+ msg.msg_controllen = CONTROLLEN;
+
+ cmptr->cmsg_level = SOL_SOCKET;
+ cmptr->cmsg_type = SCM_RIGHTS;
+ cmptr->cmsg_len = CONTROLLEN;
+ memcpy(CMSG_DATA(cmptr), &SocketFD, sizeof(int));
+
+#endif
+
+ if ( ( nSend = sendmsg(PipeFD, &msg, 0) ) > 0 )
+ {
+ bRet = sal_True;
+ OSL_TRACE("sendFdPipe : send '%i' bytes",nSend);
+
+ }
+ else
+ {
+ OSL_TRACE("sendFdPipe : sending failed (%s)",strerror(errno));
+ }
+
+ bRet = safeRead(PipeFD, &RetCode, sizeof(RetCode));
+
+ if ( bRet && RetCode == 1 )
+ {
+ OSL_TRACE("sendFdPipe : resource was received");
+ }
+ else
+ {
+ OSL_TRACE("sendFdPipe : resource wasn't received (error %s)", strerror(errno));
+ }
+
+#if defined(IOCHANNEL_TRANSFER_BSD_RENO)
+ free(cmptr);
+#endif
+
+ return bRet;
+}
+
+/**********************************************
+ receiveFdPipe
+ *********************************************/
+
+static oslSocket receiveFdPipe(int PipeFD)
+{
+ oslSocket pSocket = 0;
+ struct msghdr msghdr;
+ struct iovec iov[1];
+ char buffer[2];
+ sal_Int32 nRead;
+ int newfd=-1;
+ int nRetCode=0;
+/* char *ptr; */
+
+#if defined(IOCHANNEL_TRANSFER_BSD)
+
+ OSL_TRACE("IOCHANNEL_TRANSFER_BSD receive");
+
+ iov[0].iov_base = buffer;
+ iov[0].iov_len = sizeof(buffer);
+ msghdr.msg_name = NULL;
+ msghdr.msg_namelen = 0;
+ msghdr.msg_iov = iov;
+ msghdr.msg_iovlen = 1;
+ msghdr.msg_accrights = (caddr_t) &newfd; /* addr of descriptor */
+ msghdr.msg_accrightslen = sizeof(int); /* receive 1 descriptor */
+
+#else
+ struct cmsghdr* cmptr = (struct cmsghdr*)malloc(CONTROLLEN);
+
+ OSL_TRACE(" !!!! IOCHANNEL_TRANSFER_BSD_RENO receive");
+
+ iov[0].iov_base = buffer;
+ iov[0].iov_len = sizeof(buffer);
+ msghdr.msg_name = NULL;
+ msghdr.msg_namelen = 0;
+ msghdr.msg_iov = iov;
+ msghdr.msg_iovlen = 1;
+
+ msghdr.msg_control = (caddr_t) cmptr;
+ msghdr.msg_controllen = CONTROLLEN;
+
+#endif
+
+
+#if defined(IOCHANNEL_TRANSFER_BSD)
+
+ if ( ( nRead = recvmsg(PipeFD, &msghdr, 0) ) > 0 )
+ {
+ OSL_TRACE("receiveFdPipe : received '%i' bytes",nRead);
+ }
+#else
+
+ if ( ( ( nRead = recvmsg(PipeFD, &msghdr, 0) ) > 0 ) &&
+ ( msghdr.msg_controllen == CONTROLLEN ) )
+ {
+ OSL_TRACE("receiveFdPipe : received '%i' bytes",nRead);
+ memcpy(&newfd, CMSG_DATA(cmptr), sizeof(int));
+ }
+#endif
+ else
+ {
+ OSL_TRACE("receiveFdPipe : receiving failed (%s)",strerror(errno));
+ }
+
+ if ( newfd >= 0 )
+ {
+ pSocket = __osl_createSocketImpl(newfd);
+ nRetCode=1;
+ OSL_TRACE("received fd %i",newfd);
+ }
+
+ OSL_TRACE("receiveFdPipe : writing back %i",nRetCode);
+ if ( !safeWrite(PipeFD, &nRetCode, sizeof(nRetCode)) )
+ OSL_TRACE("write failed (%s)", strerror(errno));
+
+ if ( nRead < 0 )
+ {
+ OSL_TRACE("write failed (%s)", strerror(errno));
+ }
+ else if ( nRead != sizeof(nRetCode) )
+ {
+ // TODO: Handle this case.
+ OSL_TRACE("partial write: wrote %d out of %d)", nRead, sizeof(nRetCode));
+ }
+
+#if defined(IOCHANNEL_TRANSFER_BSD_RENO)
+ free(cmptr);
+#endif
+
+ return pSocket;
+}
+
+/**********************************************
+ osl_sendResourcePipe
+ *********************************************/
+
+sal_Bool osl_sendResourcePipe(oslPipe pPipe, oslSocket pSocket)
+{
+ sal_Bool bRet = sal_False;
+
+ if ( pSocket == 0 || pPipe == 0 )
+ {
+ return sal_False;
+ }
+
+ bRet = sendFdPipe(pPipe->m_Socket,pSocket->m_Socket);
+
+ return bRet;
+}
+
+/**********************************************
+ osl_receiveResourcePipe
+ *********************************************/
+
+oslSocket osl_receiveResourcePipe(oslPipe pPipe)
+{
+ oslSocket pSocket=0;
+
+ if ( pPipe == 0 )
+ {
+ return 0;
+ }
+
+ pSocket = receiveFdPipe(pPipe->m_Socket);
+
+ return (oslSocket) pSocket;
+}
+
+
+
+/******************************************************************************
+ *
+ * Functions for starting a process
+ *
+ *****************************************************************************/
+
+static void ChildStatusProc(void *pData)
+{
+ pid_t pid = -1;
+ int status = 0;
+ int channel[2] = { -1, -1 };
+ ProcessData data;
+ ProcessData *pdata;
+ int stdOutput[2] = { -1, -1 }, stdInput[2] = { -1, -1 }, stdError[2] = { -1, -1 };
+
+ pdata = (ProcessData *)pData;
+
+ /* make a copy of our data, because forking will only copy
+ our local stack of the thread, so the process data will not be accessible
+ in our child process */
+ memcpy(&data, pData, sizeof(data));
+
+#ifdef NO_CHILD_PROCESSES
+#define fork() (errno = EINVAL, -1)
+#endif
+ if (socketpair(AF_UNIX, SOCK_STREAM, 0, channel) == -1)
+ {
+ status = errno;
+ SAL_WARN("sal", "executeProcess socketpair() errno " << status);
+ }
+
+ fcntl(channel[0], F_SETFD, FD_CLOEXEC);
+ fcntl(channel[1], F_SETFD, FD_CLOEXEC);
+
+ /* Create redirected IO pipes */
+ if ( status == 0 && data.m_pInputWrite && pipe( stdInput ) == -1 )
+ {
+ status = errno;
+ assert(status != 0);
+ SAL_WARN("sal", "executeProcess pipe(stdInput) errno " << status);
+ }
+
+ if ( status == 0 && data.m_pOutputRead && pipe( stdOutput ) == -1 )
+ {
+ status = errno;
+ assert(status != 0);
+ SAL_WARN("sal", "executeProcess pipe(stdOutput) errno " << status);
+ }
+
+ if ( status == 0 && data.m_pErrorRead && pipe( stdError ) == -1 )
+ {
+ status = errno;
+ assert(status != 0);
+ SAL_WARN("sal", "executeProcess pipe(stdError) errno " << status);
+ }
+
+ if ( (status == 0) && ((pid = fork()) == 0) )
+ {
+ /* Child */
+ int chstatus = 0;
+ int errno_copy;
+
+ if (channel[0] != -1) close(channel[0]);
+
+ if ((data.m_uid != (uid_t)-1) && ((data.m_uid != getuid()) || (data.m_gid != getgid())))
+ {
+ OSL_ASSERT(geteuid() == 0); /* must be root */
+
+ if (! INIT_GROUPS(data.m_name, data.m_gid) || (setuid(data.m_uid) != 0))
+ OSL_TRACE("Failed to change uid and guid, errno=%d (%s)", errno, strerror(errno));
+#if defined(LINUX) || defined (FREEBSD) || defined(NETBSD) || defined(OPENBSD) || defined(DRAGONFLY)
+ unsetenv("HOME");
+#else
+ putenv("HOME=");
+#endif
+ }
+
+ if (data.m_pszDir)
+ chstatus = chdir(data.m_pszDir);
+
+ if (chstatus == 0 && ((data.m_uid == (uid_t)-1) || ((data.m_uid == getuid()) && (data.m_gid == getgid()))))
+ {
+ int i;
+ for (i = 0; data.m_pszEnv[i] != NULL; i++)
+ {
+ if (strchr(data.m_pszEnv[i], '=') == NULL)
+ {
+ unsetenv(data.m_pszEnv[i]); /*TODO: check error return*/
+ }
+ else
+ {
+ putenv(data.m_pszEnv[i]); /*TODO: check error return*/
+ }
+ }
+
+ OSL_TRACE("ChildStatusProc : starting '%s'",data.m_pszArgs[0]);
+
+ /* Connect std IO to pipe ends */
+
+ /* Write end of stdInput not used in child process */
+ if (stdInput[1] != -1) close( stdInput[1] );
+
+ /* Read end of stdOutput not used in child process */
+ if (stdOutput[0] != -1) close( stdOutput[0] );
+
+ /* Read end of stdError not used in child process */
+ if (stdError[0] != -1) close( stdError[0] );
+
+ /* Redirect pipe ends to std IO */
+
+ if ( stdInput[0] != STDIN_FILENO )
+ {
+ dup2( stdInput[0], STDIN_FILENO );
+ if (stdInput[0] != -1) close( stdInput[0] );
+ }
+
+ if ( stdOutput[1] != STDOUT_FILENO )
+ {
+ dup2( stdOutput[1], STDOUT_FILENO );
+ if (stdOutput[1] != -1) close( stdOutput[1] );
+ }
+
+ if ( stdError[1] != STDERR_FILENO )
+ {
+ dup2( stdError[1], STDERR_FILENO );
+ if (stdError[1] != -1) close( stdError[1] );
+ }
+
+ // No need to check the return value of execv. If we return from
+ // it, an error has occurred.
+ execv(data.m_pszArgs[0], (sal_Char **)data.m_pszArgs);
+ }
+
+ OSL_TRACE("Failed to exec, errno=%d (%s)", errno, strerror(errno));
+
+ OSL_TRACE("ChildStatusProc : starting '%s' failed",data.m_pszArgs[0]);
+
+ /* if we reach here, something went wrong */
+ errno_copy = errno;
+ if ( !safeWrite(channel[1], &errno_copy, sizeof(errno_copy)) )
+ OSL_TRACE("sendFdPipe : sending failed (%s)",strerror(errno));
+
+ if ( channel[1] != -1 )
+ close(channel[1]);
+
+ _exit(255);
+ }
+ else
+ { /* Parent */
+ int i = -1;
+ if (channel[1] != -1) close(channel[1]);
+
+ /* Close unused pipe ends */
+ if (stdInput[0] != -1) close( stdInput[0] );
+ if (stdOutput[1] != -1) close( stdOutput[1] );
+ if (stdError[1] != -1) close( stdError[1] );
+
+ if (pid > 0)
+ {
+ while (((i = read(channel[0], &status, sizeof(status))) < 0))
+ {
+ if (errno != EINTR)
+ break;
+ }
+ }
+
+ if (channel[0] != -1) close(channel[0]);
+
+ if ((pid > 0) && (i == 0))
+ {
+ pid_t child_pid;
+ osl_acquireMutex(ChildListMutex);
+
+ pdata->m_pProcImpl->m_pid = pid;
+ pdata->m_pProcImpl->m_pnext = ChildList;
+ ChildList = pdata->m_pProcImpl;
+
+ /* Store used pipe ends in data structure */
+
+ if ( pdata->m_pInputWrite )
+ *(pdata->m_pInputWrite) = osl::detail::createFileHandleFromFD( stdInput[1] );
+
+ if ( pdata->m_pOutputRead )
+ *(pdata->m_pOutputRead) = osl::detail::createFileHandleFromFD( stdOutput[0] );
+
+ if ( pdata->m_pErrorRead )
+ *(pdata->m_pErrorRead) = osl::detail::createFileHandleFromFD( stdError[0] );
+
+ osl_releaseMutex(ChildListMutex);
+
+ osl_setCondition(pdata->m_started);
+
+ do
+ {
+ child_pid = waitpid(pid, &status, 0);
+ } while ( 0 > child_pid && EINTR == errno );
+
+ if ( child_pid < 0)
+ {
+ OSL_TRACE("Failed to wait for child process, errno=%d (%s)", errno, strerror(errno));
+
+ /*
+ We got an other error than EINTR. Anyway we have to wake up the
+ waiting thread under any circumstances */
+
+ child_pid = pid;
+ }
+
+
+ if ( child_pid > 0 )
+ {
+ oslProcessImpl* pChild;
+
+ osl_acquireMutex(ChildListMutex);
+
+ pChild = ChildList;
+
+ /* check if it is one of our child processes */
+ while (pChild != NULL)
+ {
+ if (pChild->m_pid == child_pid)
+ {
+ if (WIFEXITED(status))
+ pChild->m_status = WEXITSTATUS(status);
+ else if (WIFSIGNALED(status))
+ pChild->m_status = 128 + WTERMSIG(status);
+ else
+ pChild->m_status = -1;
+
+ osl_setCondition(pChild->m_terminated);
+ }
+
+ pChild = pChild->m_pnext;
+ }
+
+ osl_releaseMutex(ChildListMutex);
+ }
+ }
+ else
+ {
+ OSL_TRACE("ChildStatusProc : starting '%s' failed",data.m_pszArgs[0]);
+ OSL_TRACE("Failed to launch child process, child reports errno=%d (%s)", status, strerror(status));
+
+ /* Close pipe ends */
+ if ( pdata->m_pInputWrite )
+ *pdata->m_pInputWrite = NULL;
+
+ if ( pdata->m_pOutputRead )
+ *pdata->m_pOutputRead = NULL;
+
+ if ( pdata->m_pErrorRead )
+ *pdata->m_pErrorRead = NULL;
+
+ if (stdInput[1] != -1) close( stdInput[1] );
+ if (stdOutput[0] != -1) close( stdOutput[0] );
+ if (stdError[0] != -1) close( stdError[0] );
+
+ //if pid > 0 then a process was created, even if it later failed
+ //e.g. bash searching for a command to execute, and we still
+ //need to clean it up to avoid "defunct" processes
+ if (pid > 0)
+ {
+ pid_t child_pid;
+ do
+ {
+ child_pid = waitpid(pid, &status, 0);
+ } while ( 0 > child_pid && EINTR == errno );
+ }
+
+ /* notify (and unblock) parent thread */
+ osl_setCondition(pdata->m_started);
+ }
+ }
+}
+
+/**********************************************
+ osl_executeProcess_WithRedirectedIO
+ *********************************************/
+
+oslProcessError SAL_CALL osl_executeProcess_WithRedirectedIO(
+ rtl_uString *ustrImageName,
+ rtl_uString *ustrArguments[],
+ sal_uInt32 nArguments,
+ oslProcessOption Options,
+ oslSecurity Security,
+ rtl_uString *ustrWorkDir,
+ rtl_uString *ustrEnvironment[],
+ sal_uInt32 nEnvironmentVars,
+ oslProcess *pProcess,
+ oslFileHandle *pInputWrite,
+ oslFileHandle *pOutputRead,
+ oslFileHandle *pErrorRead
+ )
+{
+
+ oslProcessError Error;
+ sal_Char* pszWorkDir=0;
+ sal_Char** pArguments=0;
+ sal_Char** pEnvironment=0;
+ unsigned int idx;
+
+ char szImagePath[PATH_MAX] = "";
+ char szWorkDir[PATH_MAX] = "";
+
+ if ( ustrImageName && ustrImageName->length )
+ {
+ FileURLToPath( szImagePath, PATH_MAX, ustrImageName );
+ }
+
+ if ( ustrWorkDir != 0 && ustrWorkDir->length )
+ {
+ FileURLToPath( szWorkDir, PATH_MAX, ustrWorkDir );
+ pszWorkDir = szWorkDir;
+ }
+
+ if ( pArguments == 0 && nArguments > 0 )
+ {
+ pArguments = (sal_Char**) malloc( ( nArguments + 2 ) * sizeof(sal_Char*) );
+ }
+
+
+ for ( idx = 0 ; idx < nArguments ; ++idx )
+ {
+ rtl_String* strArg =0;
+
+
+ rtl_uString2String( &strArg,
+ rtl_uString_getStr(ustrArguments[idx]),
+ rtl_uString_getLength(ustrArguments[idx]),
+ osl_getThreadTextEncoding(),
+ OUSTRING_TO_OSTRING_CVTFLAGS );
+
+ pArguments[idx]=strdup(rtl_string_getStr(strArg));
+ rtl_string_release(strArg);
+ pArguments[idx+1]=0;
+ }
+
+ for ( idx = 0 ; idx < nEnvironmentVars ; ++idx )
+ {
+ rtl_String* strEnv=0;
+
+ if ( pEnvironment == 0 )
+ {
+ pEnvironment = (sal_Char**) malloc( ( nEnvironmentVars + 2 ) * sizeof(sal_Char*) );
+ }
+
+ rtl_uString2String( &strEnv,
+ rtl_uString_getStr(ustrEnvironment[idx]),
+ rtl_uString_getLength(ustrEnvironment[idx]),
+ osl_getThreadTextEncoding(),
+ OUSTRING_TO_OSTRING_CVTFLAGS );
+
+ pEnvironment[idx]=strdup(rtl_string_getStr(strEnv));
+ rtl_string_release(strEnv);
+ pEnvironment[idx+1]=0;
+ }
+
+
+ Error = osl_psz_executeProcess(szImagePath,
+ pArguments,
+ Options,
+ Security,
+ pszWorkDir,
+ pEnvironment,
+ pProcess,
+ pInputWrite,
+ pOutputRead,
+ pErrorRead
+ );
+
+ if ( pArguments != 0 )
+ {
+ for ( idx = 0 ; idx < nArguments ; ++idx )
+ {
+ if ( pArguments[idx] != 0 )
+ {
+ free(pArguments[idx]);
+ }
+ }
+ free(pArguments);
+ }
+
+ if ( pEnvironment != 0 )
+ {
+ for ( idx = 0 ; idx < nEnvironmentVars ; ++idx )
+ {
+ if ( pEnvironment[idx] != 0 )
+ {
+ free(pEnvironment[idx]);
+ }
+ }
+ free(pEnvironment);
+ }
+
+ return Error;
+}
+
+/**********************************************
+ osl_executeProcess
+ *********************************************/
+
+oslProcessError SAL_CALL osl_executeProcess(
+ rtl_uString *ustrImageName,
+ rtl_uString *ustrArguments[],
+ sal_uInt32 nArguments,
+ oslProcessOption Options,
+ oslSecurity Security,
+ rtl_uString *ustrWorkDir,
+ rtl_uString *ustrEnvironment[],
+ sal_uInt32 nEnvironmentVars,
+ oslProcess *pProcess
+ )
+{
+ return osl_executeProcess_WithRedirectedIO(
+ ustrImageName,
+ ustrArguments,
+ nArguments,
+ Options,
+ Security,
+ ustrWorkDir,
+ ustrEnvironment,
+ nEnvironmentVars,
+ pProcess,
+ NULL,
+ NULL,
+ NULL
+ );
+}
+
+/**********************************************
+ osl_psz_executeProcess
+ *********************************************/
+
+oslProcessError SAL_CALL osl_psz_executeProcess(sal_Char *pszImageName,
+ sal_Char *pszArguments[],
+ oslProcessOption Options,
+ oslSecurity Security,
+ sal_Char *pszDirectory,
+ sal_Char *pszEnvironments[],
+ oslProcess *pProcess,
+ oslFileHandle *pInputWrite,
+ oslFileHandle *pOutputRead,
+ oslFileHandle *pErrorRead
+ )
+{
+ int i;
+ sal_Char path[PATH_MAX + 1];
+ ProcessData Data;
+ oslThread hThread;
+
+ path[0] = '\0';
+
+ memset(&Data,0,sizeof(ProcessData));
+ Data.m_pInputWrite = pInputWrite;
+ Data.m_pOutputRead = pOutputRead;
+ Data.m_pErrorRead = pErrorRead;
+
+ if (pszImageName == NULL)
+ pszImageName = pszArguments[0];
+
+ OSL_ASSERT(pszImageName != NULL);
+
+ if ( pszImageName == 0 )
+ {
+ return osl_Process_E_NotFound;
+ }
+
+ if ((Options & osl_Process_SEARCHPATH) &&
+ (osl_searchPath_impl(pszImageName, NULL, '\0', path, sizeof(path)) == osl_Process_E_None))
+ pszImageName = path;
+
+ Data.m_pszArgs[0] = strdup(pszImageName);
+ Data.m_pszArgs[1] = 0;
+
+ if ( pszArguments != 0 )
+ {
+ for (i = 0; ((i + 2) < MAX_ARGS) && (pszArguments[i] != NULL); i++)
+ Data.m_pszArgs[i+1] = strdup(pszArguments[i]);
+ Data.m_pszArgs[i+2] = NULL;
+ }
+
+ Data.m_options = Options;
+ Data.m_pszDir = (pszDirectory != NULL) ? strdup(pszDirectory) : NULL;
+
+ if (pszEnvironments != NULL)
+ {
+ for (i = 0; ((i + 1) < MAX_ENVS) && (pszEnvironments[i] != NULL); i++)
+ Data.m_pszEnv[i] = strdup(pszEnvironments[i]);
+ Data.m_pszEnv[i+1] = NULL;
+ }
+ else
+ Data.m_pszEnv[0] = NULL;
+
+ if (Security != NULL)
+ {
+ Data.m_uid = ((oslSecurityImpl*)Security)->m_pPasswd.pw_uid;
+ Data.m_gid = ((oslSecurityImpl*)Security)->m_pPasswd.pw_gid;
+ Data.m_name = ((oslSecurityImpl*)Security)->m_pPasswd.pw_name;
+ }
+ else
+ Data.m_uid = (uid_t)-1;
+
+ Data.m_pProcImpl = (oslProcessImpl*) malloc(sizeof(oslProcessImpl));
+ Data.m_pProcImpl->m_pid = 0;
+ Data.m_pProcImpl->m_terminated = osl_createCondition();
+ Data.m_pProcImpl->m_pnext = NULL;
+
+ if (ChildListMutex == NULL)
+ ChildListMutex = osl_createMutex();
+
+ Data.m_started = osl_createCondition();
+
+ hThread = osl_createThread(ChildStatusProc, &Data);
+
+ osl_waitCondition(Data.m_started, NULL);
+ osl_destroyCondition(Data.m_started);
+
+ for (i = 0; Data.m_pszArgs[i] != NULL; i++)
+ free((void *)Data.m_pszArgs[i]);
+
+ for (i = 0; Data.m_pszEnv[i] != NULL; i++)
+ free((void *)Data.m_pszEnv[i]);
+
+ if ( Data.m_pszDir != 0 )
+ {
+ free((void *)Data.m_pszDir);
+ }
+
+ osl_destroyThread(hThread);
+
+ if (Data.m_pProcImpl->m_pid != 0)
+ {
+ *pProcess = Data.m_pProcImpl;
+
+ if (Options & osl_Process_WAIT)
+ osl_joinProcess(*pProcess);
+
+ return osl_Process_E_None;
+ }
+
+ osl_destroyCondition(Data.m_pProcImpl->m_terminated);
+ free(Data.m_pProcImpl);
+
+ return osl_Process_E_Unknown;
+}
+
+
+/******************************************************************************
+ *
+ * Functions for processes
+ *
+ *****************************************************************************/
+
+
+/**********************************************
+ osl_terminateProcess
+ *********************************************/
+
+oslProcessError SAL_CALL osl_terminateProcess(oslProcess Process)
+{
+ if (Process == NULL)
+ return osl_Process_E_Unknown;
+
+ if (kill(((oslProcessImpl*)Process)->m_pid, SIGKILL) != 0)
+ {
+ switch (errno)
+ {
+ case EPERM:
+ return osl_Process_E_NoPermission;
+
+ case ESRCH:
+ return osl_Process_E_NotFound;
+
+ default:
+ return osl_Process_E_Unknown;
+ }
+ }
+
+ return osl_Process_E_None;
+}
+
+/**********************************************
+ osl_getProcess
+ *********************************************/
+
+oslProcess SAL_CALL osl_getProcess(oslProcessIdentifier Ident)
+{
+ oslProcessImpl *pProcImpl;
+
+ if (kill(Ident, 0) != -1)
+ {
+ oslProcessImpl* pChild;
+
+ if (ChildListMutex == NULL)
+ ChildListMutex = osl_createMutex();
+
+ osl_acquireMutex(ChildListMutex);
+
+ pChild = ChildList;
+
+ /* check if it is one of our child processes */
+ while (pChild != NULL)
+ {
+ if (Ident == (sal_uInt32) pChild->m_pid)
+ break;
+
+ pChild = pChild->m_pnext;
+ }
+
+ pProcImpl = (oslProcessImpl*) malloc(sizeof(oslProcessImpl));
+ pProcImpl->m_pid = Ident;
+ pProcImpl->m_terminated = osl_createCondition();
+
+ if (pChild != NULL)
+ {
+ /* process is a child so insert into list */
+ pProcImpl->m_pnext = pChild->m_pnext;
+ pChild->m_pnext = pProcImpl;
+
+ pProcImpl->m_status = pChild->m_status;
+
+ if (osl_checkCondition(pChild->m_terminated))
+ osl_setCondition(pProcImpl->m_terminated);
+ }
+ else
+ pProcImpl->m_pnext = NULL;
+
+ osl_releaseMutex(ChildListMutex);
+ }
+ else
+ pProcImpl = NULL;
+
+ return (pProcImpl);
+}
+
+/**********************************************
+ osl_freeProcessHandle
+ *********************************************/
+
+void SAL_CALL osl_freeProcessHandle(oslProcess Process)
+{
+ if (Process != NULL)
+ {
+ oslProcessImpl *pChild, *pPrev = NULL;
+
+ OSL_ASSERT(ChildListMutex != NULL);
+
+ if ( ChildListMutex == 0 )
+ {
+ return;
+ }
+
+ osl_acquireMutex(ChildListMutex);
+
+ pChild = ChildList;
+
+ /* remove process from child list */
+ while (pChild != NULL)
+ {
+ if (pChild == (oslProcessImpl*)Process)
+ {
+ if (pPrev != NULL)
+ pPrev->m_pnext = pChild->m_pnext;
+ else
+ ChildList = pChild->m_pnext;
+
+ break;
+ }
+
+ pPrev = pChild;
+ pChild = pChild->m_pnext;
+ }
+
+ osl_releaseMutex(ChildListMutex);
+
+ osl_destroyCondition(((oslProcessImpl*)Process)->m_terminated);
+
+ free(Process);
+ }
+}
+
+#if defined(LINUX)
+struct osl_procStat
+{
+ /* from 'stat' */
+ pid_t pid; /* pid */
+ char command[16]; /* 'argv[0]' */ /* mfe: it all right char comm[16] in kernel! */
+ char state; /* state (running, stopped, ...) */
+ pid_t ppid; /* parent pid */
+ pid_t pgrp; /* parent group */
+ int session; /* session ID */
+ int tty; /* no of tty */
+ pid_t tpgid; /* group of process owning the tty */
+ unsigned long flags; /* flags dunno */
+ unsigned long minflt; /* minor page faults */
+ unsigned long cminflt; /* minor page faults with children */
+ unsigned long majflt; /* major page faults */
+ unsigned long cmajflt; /* major page faults with children */
+ unsigned long utime; /* no of jiffies in user mode */
+ unsigned long stime; /* no of jiffies in kernel mode */
+ unsigned long cutime; /* no of jiffies in user mode with children */
+ unsigned long cstime; /* no of jiffies in kernel mode with children */
+ unsigned long priority; /* nice value + 15 (kernel scheduling prio)*/
+ long nice; /* nice value */
+ long timeout; /* no of jiffies of next process timeout */
+ long itrealvalue; /* no jiffies before next SIGALRM */
+ unsigned long starttime; /* process started this no of jiffies after boot */
+ unsigned long vsize; /* virtual memory size (in bytes) */
+ long rss; /* resident set size (in pages) */
+ unsigned long rss_rlim; /* rss limit (in bytes) */
+ unsigned long startcode; /* address above program text can run */
+ unsigned long endcode; /* address below program text can run */
+ unsigned long startstack; /* address of start of stack */
+ unsigned long kstkesp; /* current value of 'esp' (stack pointer) */
+ unsigned long kstkeip; /* current value of 'eip' (instruction pointer) */
+ /* mfe: Linux > 2.1.7x have more signals (88) */
+/*#ifdef LINUX */
+ char signal[24]; /* pending signals */
+ char blocked[24]; /* blocked signals */
+ char sigignore[24]; /* ignored signals */
+ char sigcatch[24]; /* catched signals */
+/*#else*/
+/* long long signal;*/
+/* long long blocked;*/
+/* long long sigignore;*/
+/* long long sigcatch;*/
+/*#endif */
+ unsigned long wchan; /* 'channel' the process is waiting in */
+ unsigned long nswap; /* ? */
+ unsigned long cnswap; /* ? */
+
+ /* from 'status' */
+ int ruid; /* real uid */
+ int euid; /* effective uid */
+ int suid; /* saved uid */
+ int fuid; /* file access uid */
+ int rgid; /* real gid */
+ int egid; /* effective gid */
+ int sgid; /* saved gid */
+ int fgid; /* file access gid */
+ unsigned long vm_size; /* like vsize but on kb */
+ unsigned long vm_lock; /* locked pages in kb */
+ unsigned long vm_rss; /* like rss but in kb */
+ unsigned long vm_data; /* data size */
+ unsigned long vm_stack; /* stack size */
+ unsigned long vm_exe; /* executable size */
+ unsigned long vm_lib; /* library size */
+};
+
+/**********************************************
+ osl_getProcStat
+ *********************************************/
+
+sal_Bool osl_getProcStat(pid_t pid, struct osl_procStat* procstat)
+{
+ int fd = 0;
+ sal_Bool bRet = sal_False;
+ char name[PATH_MAX + 1];
+ snprintf(name, sizeof(name), "/proc/%u/stat", pid);
+
+ if ((fd = open(name,O_RDONLY)) >=0 )
+ {
+ char* tmp=0;
+ char prstatbuf[512];
+ memset(prstatbuf,0,512);
+ bRet = safeRead(fd, prstatbuf, 511);
+
+ close(fd);
+ /*printf("%s\n\n",prstatbuf);*/
+
+ if (!bRet)
+ return sal_False;
+
+ tmp = strrchr(prstatbuf, ')');
+ *tmp = '\0';
+ memset(procstat->command, 0, sizeof(procstat->command));
+
+ sscanf(prstatbuf, "%d (%15c", &procstat->pid, procstat->command);
+ sscanf(tmp + 2,
+ "%c"
+ "%i %i %i %i %i"
+ "%lu %lu %lu %lu %lu"
+ "%lu %lu %lu %lu"
+ "%lu %li %li %li"
+ "%lu %lu %li %lu"
+ "%lu %lu %lu %lu %lu"
+ "%s %s %s %s"
+ "%lu %lu %lu",
+ &procstat->state,
+ &procstat->ppid, &procstat->pgrp, &procstat->session, &procstat->tty, &procstat->tpgid,
+ &procstat->flags, &procstat->minflt, &procstat->cminflt, &procstat->majflt, &procstat->cmajflt,
+ &procstat->utime, &procstat->stime, &procstat->cutime, &procstat->cstime,
+ &procstat->priority, &procstat->nice, &procstat->timeout, &procstat->itrealvalue,
+ &procstat->starttime, &procstat->vsize, &procstat->rss, &procstat->rss_rlim,
+ &procstat->startcode, &procstat->endcode, &procstat->startstack, &procstat->kstkesp, &procstat->kstkeip,
+ procstat->signal, procstat->blocked, procstat->sigignore, procstat->sigcatch,
+ &procstat->wchan, &procstat->nswap, &procstat->cnswap
+ );
+ }
+ return bRet;
+}
+
+/**********************************************
+ osl_getProcStatus
+ *********************************************/
+
+sal_Bool osl_getProcStatus(pid_t pid, struct osl_procStat* procstat)
+{
+ int fd = 0;
+ char name[PATH_MAX + 1];
+ sal_Bool bRet = sal_False;
+
+ snprintf(name, sizeof(name), "/proc/%u/status", pid);
+
+ if ((fd = open(name,O_RDONLY)) >=0 )
+ {
+ char* tmp=0;
+ char prstatusbuf[512];
+ memset(prstatusbuf,0,512);
+ bRet = safeRead(fd, prstatusbuf, 511);
+
+ close(fd);
+
+ /* printf("\n\n%s\n\n",prstatusbuf);*/
+
+ if (!bRet)
+ return sal_False;
+
+ tmp = strstr(prstatusbuf,"Uid:");
+ if(tmp)
+ {
+ sscanf(tmp,"Uid:\t%d\t%d\t%d\t%d",
+ &procstat->ruid, &procstat->euid, &procstat->suid, &procstat->fuid
+ );
+ }
+
+
+ tmp = strstr(prstatusbuf,"Gid:");
+ if(tmp)
+ {
+ sscanf(tmp,"Gid:\t%d\t%d\t%d\t%d",
+ &procstat->rgid, &procstat->egid, &procstat->sgid, &procstat->fgid
+ );
+ }
+
+ tmp = strstr(prstatusbuf,"VmSize:");
+ if(tmp)
+ {
+ sscanf(tmp,
+ "VmSize: %lu kB\n"
+ "VmLck: %lu kB\n"
+ "VmRSS: %lu kB\n"
+ "VmData: %lu kB\n"
+ "VmStk: %lu kB\n"
+ "VmExe: %lu kB\n"
+ "VmLib: %lu kB\n",
+ &procstat->vm_size, &procstat->vm_lock, &procstat->vm_rss, &procstat->vm_data,
+ &procstat->vm_stack, &procstat->vm_exe, &procstat->vm_lib
+ );
+ }
+
+ tmp = strstr(prstatusbuf,"SigPnd:");
+ if(tmp)
+ {
+ sscanf(tmp, "SigPnd: %s SigBlk: %s SigIgn: %s %*s %s",
+ procstat->signal, procstat->blocked, procstat->sigignore, procstat->sigcatch
+ );
+ }
+ }
+ return bRet;
+}
+
+#endif
+
+/**********************************************
+ osl_getProcessInfo
+ *********************************************/
+
+oslProcessError SAL_CALL osl_getProcessInfo(oslProcess Process, oslProcessData Fields, oslProcessInfo* pInfo)
+{
+ pid_t pid;
+
+ if (Process == NULL)
+ pid = getpid();
+ else
+ pid = ((oslProcessImpl*)Process)->m_pid;
+
+ if (! pInfo || (pInfo->Size != sizeof(oslProcessInfo)))
+ return osl_Process_E_Unknown;
+
+ pInfo->Fields = 0;
+
+ if (Fields & osl_Process_IDENTIFIER)
+ {
+ pInfo->Ident = pid;
+ pInfo->Fields |= osl_Process_IDENTIFIER;
+ }
+
+ if (Fields & osl_Process_EXITCODE)
+ {
+ if ((Process != NULL) &&
+ osl_checkCondition(((oslProcessImpl*)Process)->m_terminated))
+ {
+ pInfo->Code = ((oslProcessImpl*)Process)->m_status;
+ pInfo->Fields |= osl_Process_EXITCODE;
+ }
+ }
+
+ if (Fields & (osl_Process_HEAPUSAGE | osl_Process_CPUTIMES))
+ {
+
+#if defined(SOLARIS)
+
+ int fd;
+ sal_Char name[PATH_MAX + 1];
+
+ snprintf(name, sizeof(name), "/proc/%u", pid);
+
+ if ((fd = open(name, O_RDONLY)) >= 0)
+ {
+ prstatus_t prstatus;
+
+ if (ioctl(fd, PIOCSTATUS, &prstatus) >= 0)
+ {
+ if (Fields & osl_Process_CPUTIMES)
+ {
+ pInfo->UserTime.Seconds = prstatus.pr_utime.tv_sec;
+ pInfo->UserTime.Nanosec = prstatus.pr_utime.tv_nsec;
+ pInfo->SystemTime.Seconds = prstatus.pr_stime.tv_sec;
+ pInfo->SystemTime.Nanosec = prstatus.pr_stime.tv_nsec;
+
+ pInfo->Fields |= osl_Process_CPUTIMES;
+ }
+
+ if (Fields & osl_Process_HEAPUSAGE)
+ {
+ pInfo->HeapUsage = prstatus.pr_brksize;
+
+ pInfo->Fields |= osl_Process_HEAPUSAGE;
+ }
+
+ close(fd);
+
+ return (pInfo->Fields == Fields) ? osl_Process_E_None : osl_Process_E_Unknown;
+ }
+ else
+ close(fd);
+ }
+
+#elif defined(LINUX)
+
+ if ( (Fields & osl_Process_CPUTIMES) || (Fields & osl_Process_HEAPUSAGE) )
+ {
+ struct osl_procStat procstat;
+ memset(&procstat,0,sizeof(procstat));
+
+ if ( (Fields & osl_Process_CPUTIMES) && osl_getProcStat(pid, &procstat) )
+ {
+ /*
+ * mfe:
+ * We calculate only time of the process proper.
+ * Threads are processes, we do not consider their time here!
+ * (For this, cutime and cstime should be used, it seems not
+ * to work in 2.0.36)
+ */
+
+ long clktck;
+ unsigned long hz;
+ unsigned long userseconds;
+ unsigned long systemseconds;
+
+ clktck = sysconf(_SC_CLK_TCK);
+ if (clktck < 0) {
+ return osl_Process_E_Unknown;
+ }
+ hz = (unsigned long) clktck;
+
+ userseconds = procstat.utime/hz;
+ systemseconds = procstat.stime/hz;
+
+ pInfo->UserTime.Seconds = userseconds;
+ pInfo->UserTime.Nanosec = procstat.utime - (userseconds * hz);
+ pInfo->SystemTime.Seconds = systemseconds;
+ pInfo->SystemTime.Nanosec = procstat.stime - (systemseconds * hz);
+
+ pInfo->Fields |= osl_Process_CPUTIMES;
+ }
+
+ if ( (Fields & osl_Process_HEAPUSAGE) && osl_getProcStatus(pid, &procstat) )
+ {
+ /*
+ * mfe:
+ * vm_data (found in status) shows the size of the data segment
+ * it a rough approximation of the core heap size
+ */
+ pInfo->HeapUsage = procstat.vm_data*1024;
+
+ pInfo->Fields |= osl_Process_HEAPUSAGE;
+ }
+ }
+
+ return (pInfo->Fields == Fields) ? osl_Process_E_None : osl_Process_E_Unknown;
+#endif
+
+ }
+
+ return (pInfo->Fields == Fields) ? osl_Process_E_None : osl_Process_E_Unknown;
+}
+
+
+/***********************************************
+ helper function for osl_joinProcessWithTimeout
+ **********************************************/
+
+static int is_timeout(const struct timeval* tend)
+{
+ struct timeval tcurrent;
+ gettimeofday(&tcurrent, NULL);
+ return (tcurrent.tv_sec >= tend->tv_sec);
+}
+
+/**********************************************
+ kill(pid, 0) is usefull for checking if a
+ process is still alive, but remember that
+ kill even returns 0 if the process is already
+ a zombie.
+ *********************************************/
+
+static int is_process_dead(pid_t pid)
+{
+ return ((-1 == kill(pid, 0)) && (ESRCH == errno));
+}
+
+/**********************************************
+ osl_joinProcessWithTimeout
+ *********************************************/
+
+oslProcessError SAL_CALL osl_joinProcessWithTimeout(oslProcess Process, const TimeValue* pTimeout)
+{
+ oslProcessImpl* pChild = ChildList;
+ oslProcessError osl_error = osl_Process_E_None;
+
+ OSL_PRECOND(Process, "osl_joinProcess: Invalid parameter");
+ OSL_ASSERT(ChildListMutex);
+
+ if (NULL == Process || 0 == ChildListMutex)
+ return osl_Process_E_Unknown;
+
+ osl_acquireMutex(ChildListMutex);
+
+ /* check if process is a child of ours */
+ while (pChild != NULL)
+ {
+ if (pChild == (oslProcessImpl*)Process)
+ break;
+
+ pChild = pChild->m_pnext;
+ }
+
+ osl_releaseMutex(ChildListMutex);
+
+ if (pChild != NULL)
+ {
+ oslConditionResult cond_res = osl_waitCondition(pChild->m_terminated, pTimeout);
+
+ if (osl_cond_result_timeout == cond_res)
+ osl_error = osl_Process_E_TimedOut;
+ else if (osl_cond_result_ok != cond_res)
+ osl_error = osl_Process_E_Unknown;
+ }
+ else /* alien process; StatusThread will not be able
+ to set the condition terminated */
+ {
+ pid_t pid = ((oslProcessImpl*)Process)->m_pid;
+
+ if (pTimeout)
+ {
+ int timeout = 0;
+ struct timeval tend;
+
+ gettimeofday(&tend, NULL);
+
+ tend.tv_sec += pTimeout->Seconds;
+
+ while (!is_process_dead(pid) && ((timeout = is_timeout(&tend)) == 0))
+ sleep(1);
+
+ if (timeout)
+ osl_error = osl_Process_E_TimedOut;
+ }
+ else /* infinite */
+ {
+ while (!is_process_dead(pid))
+ sleep(1);
+ }
+ }
+ return osl_error;
+}
+
+/**********************************************
+ osl_joinProcess
+ *********************************************/
+
+oslProcessError SAL_CALL osl_joinProcess(oslProcess Process)
+{
+ return osl_joinProcessWithTimeout(Process, NULL);
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
More information about the Libreoffice-commits
mailing list