You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by mt...@apache.org on 2011/04/27 11:48:54 UTC

svn commit: r1097056 - in /commons/sandbox/runtime/trunk/src/main: java/org/apache/commons/runtime/ java/org/apache/commons/runtime/platform/unix/ java/org/apache/commons/runtime/platform/windows/ native/ native/include/acr/ native/os/unix/ native/shared/

Author: mturk
Date: Wed Apr 27 09:48:53 2011
New Revision: 1097056

URL: http://svn.apache.org/viewvc?rev=1097056&view=rev
Log:
Add Exec stub

Added:
    commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/Exec.java   (with props)
    commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/ExecImpl.java   (with props)
    commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/platform/unix/PosixExec.java   (with props)
    commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/platform/unix/PosixExecImpl.java   (with props)
    commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/platform/windows/WindowsExec.java   (with props)
    commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/platform/windows/WindowsExecImpl.java   (with props)
    commons/sandbox/runtime/trunk/src/main/native/os/unix/exec.c   (with props)
Modified:
    commons/sandbox/runtime/trunk/src/main/native/Makefile.unx.in
    commons/sandbox/runtime/trunk/src/main/native/include/acr/sbuf.h
    commons/sandbox/runtime/trunk/src/main/native/include/acr/stdtypes.h
    commons/sandbox/runtime/trunk/src/main/native/include/acr/string.h
    commons/sandbox/runtime/trunk/src/main/native/os/unix/arch_opts.h
    commons/sandbox/runtime/trunk/src/main/native/os/unix/util.c
    commons/sandbox/runtime/trunk/src/main/native/shared/string.c

Added: commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/Exec.java
URL: http://svn.apache.org/viewvc/commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/Exec.java?rev=1097056&view=auto
==============================================================================
--- commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/Exec.java (added)
+++ commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/Exec.java Wed Apr 27 09:48:53 2011
@@ -0,0 +1,51 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.runtime;
+
+/**
+ * Exec class.
+ * <p>
+ * </p>
+ *
+ * @since Runtime 1.0
+ */
+public abstract class Exec
+{
+
+    protected Exec()
+    {
+        // No Instance
+    }
+
+    private static final  ExecImpl impl;
+
+    static {
+        impl = ExecImpl.get();
+    }
+
+    protected String  name;
+    protected boolean owner;
+
+    public static Exec create()
+        throws OperationNotImplementedException,
+               SystemException
+    {
+        if (impl == null)
+            throw new OperationNotImplementedException();
+        return impl.create();
+    }
+
+}

Propchange: commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/Exec.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/ExecImpl.java
URL: http://svn.apache.org/viewvc/commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/ExecImpl.java?rev=1097056&view=auto
==============================================================================
--- commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/ExecImpl.java (added)
+++ commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/ExecImpl.java Wed Apr 27 09:48:53 2011
@@ -0,0 +1,51 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.runtime;
+
+/**
+ * ExecImpl class.
+ * <p>
+ * </p>
+ *
+ * @since Runtime 1.0
+ */
+public abstract class ExecImpl
+{
+    private static final  ExecImpl impl;
+    private static native ExecImpl init0()
+        throws OutOfMemoryError;
+
+    static {
+        impl = init0();
+    }
+
+    protected ExecImpl()
+    {
+        // No Instance
+    }
+
+    public static final ExecImpl get()
+        throws OperationNotImplementedException
+    {
+        if (impl == null)
+            throw new OperationNotImplementedException();
+        return impl;
+    }
+
+    public abstract Exec create();
+
+}
+

Propchange: commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/ExecImpl.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/platform/unix/PosixExec.java
URL: http://svn.apache.org/viewvc/commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/platform/unix/PosixExec.java?rev=1097056&view=auto
==============================================================================
--- commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/platform/unix/PosixExec.java (added)
+++ commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/platform/unix/PosixExec.java Wed Apr 27 09:48:53 2011
@@ -0,0 +1,39 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.runtime.platform.unix;
+
+import org.apache.commons.runtime.Exec;
+import org.apache.commons.runtime.Errno;
+import org.apache.commons.runtime.Status;
+import org.apache.commons.runtime.InvalidArgumentException;
+import org.apache.commons.runtime.SystemException;
+
+/**
+ * PosixExec class.
+ * <p>
+ * </p>
+ *
+ * @since Runtime 1.0
+ */
+final class PosixExec extends Exec
+{
+
+    public PosixExec()
+    {
+
+    }
+
+}

Propchange: commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/platform/unix/PosixExec.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/platform/unix/PosixExecImpl.java
URL: http://svn.apache.org/viewvc/commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/platform/unix/PosixExecImpl.java?rev=1097056&view=auto
==============================================================================
--- commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/platform/unix/PosixExecImpl.java (added)
+++ commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/platform/unix/PosixExecImpl.java Wed Apr 27 09:48:53 2011
@@ -0,0 +1,41 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.runtime.platform.unix;
+
+import org.apache.commons.runtime.Exec;
+import org.apache.commons.runtime.ExecImpl;
+
+/**
+ * PosixExecImpl class.
+ * <p>
+ * </p>
+ *
+ * @since Runtime 1.0
+ */
+final class PosixExecImpl extends ExecImpl
+{
+
+    public PosixExecImpl()
+    {
+        // No Instance
+    }
+
+    public Exec create()
+    {
+        return new PosixExec();
+    }
+
+}

Propchange: commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/platform/unix/PosixExecImpl.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/platform/windows/WindowsExec.java
URL: http://svn.apache.org/viewvc/commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/platform/windows/WindowsExec.java?rev=1097056&view=auto
==============================================================================
--- commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/platform/windows/WindowsExec.java (added)
+++ commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/platform/windows/WindowsExec.java Wed Apr 27 09:48:53 2011
@@ -0,0 +1,39 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.runtime.platform.windows;
+
+import org.apache.commons.runtime.Exec;
+import org.apache.commons.runtime.Errno;
+import org.apache.commons.runtime.Status;
+import org.apache.commons.runtime.InvalidArgumentException;
+import org.apache.commons.runtime.SystemException;
+
+/**
+ * WindowsExec class.
+ * <p>
+ * </p>
+ *
+ * @since Runtime 1.0
+ */
+final class WindowsExec extends Exec
+{
+
+    public WindowsExec()
+    {
+
+    }
+
+}

Propchange: commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/platform/windows/WindowsExec.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/platform/windows/WindowsExecImpl.java
URL: http://svn.apache.org/viewvc/commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/platform/windows/WindowsExecImpl.java?rev=1097056&view=auto
==============================================================================
--- commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/platform/windows/WindowsExecImpl.java (added)
+++ commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/platform/windows/WindowsExecImpl.java Wed Apr 27 09:48:53 2011
@@ -0,0 +1,41 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.runtime.platform.windows;
+
+import org.apache.commons.runtime.Exec;
+import org.apache.commons.runtime.ExecImpl;
+
+/**
+ * WindowsExecImpl class.
+ * <p>
+ * </p>
+ *
+ * @since Runtime 1.0
+ */
+final class WindowsExecImpl extends ExecImpl
+{
+
+    public WindowsExecImpl()
+    {
+        // No Instance
+    }
+
+    public Exec create()
+    {
+        return new WindowsExec();
+    }
+
+}

Propchange: commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/platform/windows/WindowsExecImpl.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: commons/sandbox/runtime/trunk/src/main/native/Makefile.unx.in
URL: http://svn.apache.org/viewvc/commons/sandbox/runtime/trunk/src/main/native/Makefile.unx.in?rev=1097056&r1=1097055&r2=1097056&view=diff
==============================================================================
--- commons/sandbox/runtime/trunk/src/main/native/Makefile.unx.in (original)
+++ commons/sandbox/runtime/trunk/src/main/native/Makefile.unx.in Wed Apr 27 09:48:53 2011
@@ -61,6 +61,7 @@ ASMSOURCES=\
 
 UNIX_SOURCES=\
 	$(TOPDIR)/os/unix/dso.c \
+	$(TOPDIR)/os/unix/exec.c \
 	$(TOPDIR)/os/unix/execmem.c \
 	$(TOPDIR)/os/unix/init.c \
 	$(TOPDIR)/os/unix/platform.c \

Modified: commons/sandbox/runtime/trunk/src/main/native/include/acr/sbuf.h
URL: http://svn.apache.org/viewvc/commons/sandbox/runtime/trunk/src/main/native/include/acr/sbuf.h?rev=1097056&r1=1097055&r2=1097056&view=diff
==============================================================================
--- commons/sandbox/runtime/trunk/src/main/native/include/acr/sbuf.h (original)
+++ commons/sandbox/runtime/trunk/src/main/native/include/acr/sbuf.h Wed Apr 27 09:48:53 2011
@@ -68,7 +68,7 @@ char     *AcrSbTrim(acr_sb_t *);
 int       AcrSbOverflowed(acr_sb_t *);
 void      AcrSbFinish(acr_sb_t *);
 void      AcrSbFlush(acr_sb_t *);
-char     *AcrSbFetach(acr_sb_t *);
+char     *AcrSbDetach(acr_sb_t *);
 int       AcrSbLen(acr_sb_t *);
 int       AcrSbCapacity(acr_sb_t *);
 int       AcrSbDone(acr_sb_t *);

Modified: commons/sandbox/runtime/trunk/src/main/native/include/acr/stdtypes.h
URL: http://svn.apache.org/viewvc/commons/sandbox/runtime/trunk/src/main/native/include/acr/stdtypes.h?rev=1097056&r1=1097055&r2=1097056&view=diff
==============================================================================
--- commons/sandbox/runtime/trunk/src/main/native/include/acr/stdtypes.h (original)
+++ commons/sandbox/runtime/trunk/src/main/native/include/acr/stdtypes.h Wed Apr 27 09:48:53 2011
@@ -164,4 +164,12 @@ struct rlimit {
 # define IOV_MAX        1024
 #endif
 
+/** Generic buffer structure */
+typedef struct acr_buf_t {
+    char       *buf;
+    acr_size_t  len;
+    acr_size_t  pos;
+    acr_size_t  use;
+} acr_buf_t;
+
 #endif /* _ACR_STDTYPES_H_ */

Modified: commons/sandbox/runtime/trunk/src/main/native/include/acr/string.h
URL: http://svn.apache.org/viewvc/commons/sandbox/runtime/trunk/src/main/native/include/acr/string.h?rev=1097056&r1=1097055&r2=1097056&view=diff
==============================================================================
--- commons/sandbox/runtime/trunk/src/main/native/include/acr/string.h (original)
+++ commons/sandbox/runtime/trunk/src/main/native/include/acr/string.h Wed Apr 27 09:48:53 2011
@@ -169,6 +169,16 @@ AcrMszStrToStringArrayA(JNI_STDENV, cons
 jobjectArray
 AcrMszStrToStringArrayW(JNI_STDENV, const wchar_t *s);
 
+void
+AcrFreeStringArray(void **arr);
+
+char **
+AcrGetJavaStringArrayA(JNI_STDENV, jobjectArray arr);
+
+wchar_t **
+AcrGetJavaStringArrayW(JNI_STDENV, jobjectArray arr);
+
+
 #ifdef __cplusplus
 }
 #endif

Modified: commons/sandbox/runtime/trunk/src/main/native/os/unix/arch_opts.h
URL: http://svn.apache.org/viewvc/commons/sandbox/runtime/trunk/src/main/native/os/unix/arch_opts.h?rev=1097056&r1=1097055&r2=1097056&view=diff
==============================================================================
--- commons/sandbox/runtime/trunk/src/main/native/os/unix/arch_opts.h (original)
+++ commons/sandbox/runtime/trunk/src/main/native/os/unix/arch_opts.h Wed Apr 27 09:48:53 2011
@@ -41,6 +41,19 @@ ACR_INLINE(int) s_close(int fd)
         return r_close(fd);
 }
 
+ACR_INLINE(int) i_close(int *fd)
+{
+    if (fd != 0) {
+        int fc = *fd;
+        *fd = -1;
+        return s_close(fc);
+    }
+    else {
+        errno = EINVAL;
+        return -1;
+    }
+}
+
 /* restartable dup2() */
 ACR_INLINE(int) r_dup2(int oldfd, int newfd)
 {
@@ -74,11 +87,70 @@ ACR_INLINE(ssize_t) r_write(int fd, cons
     return w;
 }
 
+/* restartable pread() */
+ACR_INLINE(ssize_t) r_pread(int fd, void *buf, size_t count, off_t offset)
+{
+    ssize_t r;
+    do {
+        r = pread(fd, buf, count, offset);
+    } while (r == -1 && errno == EINTR);
+
+    return r;
+}
+
+/* restartable pwrite() */
+ACR_INLINE(ssize_t) r_pwrite(int fd, const void *buf, size_t count, off_t offset)
+{
+    ssize_t w;
+    do {
+        w = pwrite(fd, buf, count, offset);
+    } while (w == -1 && errno == EINTR);
+
+    return w;
+}
+
+ACR_INLINE(ssize_t) f_write(int fd, const void *buf, size_t count)
+{
+    ssize_t t = 0;
+    ssize_t w;
+    ssize_t c = (ssize_t)count;
+    const char *p = (const char *)buf;
+    do {
+        w = r_write(fd, p, c);
+        if (w > 0) {
+            p += w;
+            c -= w;
+            t += w;
+        }
+    } while (w >= 0 && c > 0);
+    return t;
+}
+
+ACR_INLINE(ssize_t) f_read(int fd, void *buf, size_t count)
+{
+    ssize_t t = 0;
+    ssize_t r;
+    ssize_t c = (ssize_t)count;
+    char *p   = (char *)buf;
+    do {
+        r = r_read(fd, p, c);
+        if (r > 0) {
+            p += r;
+            c -= r;
+            t += r;
+        }
+    } while (r >= 0 && c > 0);
+    return t;
+}
+
+int     AcrFdwalk(int (*func)(void *data , int fd), void *cd);
 int     AcrNonblock(int fd, int on);
 int     AcrCloseOnExec(int fd, int on);
 int     AcrWaitIO(int fd, int timeout, int events);
 int     AcrNullPipe(int flags, int fd);
 int     AcrPipePair(int pd[2], int flags);
+int     AcrSigIgnore(int signo);
+int     AcrSigDefault(int signo);
 
 
 #endif /* _ACR_ARCH_OPTS_H_ */

Added: commons/sandbox/runtime/trunk/src/main/native/os/unix/exec.c
URL: http://svn.apache.org/viewvc/commons/sandbox/runtime/trunk/src/main/native/os/unix/exec.c?rev=1097056&view=auto
==============================================================================
--- commons/sandbox/runtime/trunk/src/main/native/os/unix/exec.c (added)
+++ commons/sandbox/runtime/trunk/src/main/native/os/unix/exec.c Wed Apr 27 09:48:53 2011
@@ -0,0 +1,650 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "acr/error.h"
+#include "acr/clazz.h"
+#include "acr/memory.h"
+#include "acr/iodefs.h"
+#include "acr/port.h"
+#include "acr/sbuf.h"
+#include "acr/time.h"
+#include "arch_opts.h"
+#include <poll.h>
+
+#define PROC_TIMEOUT_STEP   100
+#define PROC_BUFFER_SIZE    512
+
+#define PIPE_STDINP         0
+#define PIPE_STDINP_RDS     0
+#define PIPE_STDINP_WRS     1
+#define PIPE_STDOUT         2
+#define PIPE_STDOUT_RDS     2
+#define PIPE_STDOUT_WRS     3
+#define PIPE_STDERR         4
+#define PIPE_STDERR_RDS     4
+#define PIPE_STDERR_WRS     5
+#define PIPE_SIGERR         6
+#define PIPE_SIGERR_RDS     6
+#define PIPE_SIGERR_WRS     7
+#define PIPE_SIGPID         8
+#define PIPE_SIGPID_RDS     8
+#define PIPE_SIGPID_WRS     9
+#define PIPE_COUNT         10
+
+typedef struct acr_limit_t {
+    /** Process timeout in miliseconds
+     */
+    int             timeout;
+    struct rlimit  *cpu;
+    struct rlimit  *mem;
+    struct rlimit  *nproc;
+    struct rlimit  *nfile;
+} acr_limit_t;
+
+typedef struct acr_proc_t {
+    /** Process timeout in miliseconds
+     */
+    acr_limit_t     limit;
+    pid_t           pid;
+    int             flags;
+    int             exitwhy;
+    int             exitval;
+    uid_t           uid;
+    gid_t           gid;
+    mode_t          mask;
+    acr_buf_t       out;
+    acr_buf_t       err;
+} acr_proc_t;
+
+J_DECLARE_CLAZZ = {
+    INVALID_FIELD_OFFSET,
+    0,
+    0,
+    0,
+   ACR_UNX_CP "PosixExecImpl"
+};
+
+J_DECLARE_M_ID(0000) = {
+    0,
+    "<init>",
+    "()V"
+};
+
+static int _setplimit(acr_limit_t *limit)
+{
+    if (limit == 0)
+        return 0;
+#if HAVE_SETRLIMIT
+#ifdef RLIMIT_CPU
+    if (limit->cpu != 0 &&
+        setrlimit(RLIMIT_CPU, limit->cpu) != 0)
+            return errno;
+#endif
+#ifdef RLIMIT_NPROC
+    if (limit->nproc != 0 &&
+        setrlimit(RLIMIT_NPROC, limit->nproc) != 0)
+        return errno;
+#endif
+#ifdef RLIMIT_NOFILE
+    if (limit->nfile != 0 &&
+        setrlimit(RLIMIT_NOFILE,limit->nfile) != 0)
+        return errno;
+#endif
+#if defined(RLIMIT_AS)
+    if (limit->mem != 0 &&
+        setrlimit(RLIMIT_AS, limit->mem) != 0)
+        return errno;
+#elif defined(RLIMIT_DATA)
+    if (limit->mem != 0 &&
+        setrlimit(RLIMIT_DATA, limit->mem) != 0)
+        return errno;
+#elif defined(RLIMIT_VMEM)
+    if (limit->mem != 0 &&
+        setrlimit(RLIMIT_VMEM, limit->mem) != 0)
+        return errno;
+#endif
+#endif
+    return 0;
+}
+
+static int _fdwalker(void *data , int fd)
+{
+    int  i;
+    int *pipes = (int *)data;
+
+    if (fd < 3) {
+        /* Do not close std file descriptors
+         */
+        return 0;
+    }
+    for (i = 0; i < PIPE_COUNT; i++) {
+        if (pipes[i] == fd) {
+            /* This is one of our own's.
+             */
+            return 0;
+        }
+    }
+    /* Close the file
+     */
+    return r_close(fd);
+}
+
+static int _run_exec(const char *executable,
+                     char *const *argv,
+                     char *const *envp,
+                     const char *workdir,
+                     acr_buf_t *out,
+                     acr_buf_t *err,
+                     acr_buf_t *inp,
+                     acr_limit_t *limit,
+                     int *retval)
+{
+    int   i, rc   = 0;
+    int   exitwhy = 0;
+    int   exitval = 0;
+    int   pipes[PIPE_COUNT] = { -1, -1, -1, -1,  -1, -1, -1, -1, -1, -1 };
+    int   sigerr = 0;
+    int   detach = 0;
+    pid_t pid;
+    pid_t sigpid = 0;
+    acr_sb_t   obuf_s;
+    acr_sb_t   ebuf_s;
+    acr_sb_t  *obuf = 0;
+    acr_sb_t  *ebuf = 0;
+    acr_buf_t  ibuf = { 0, 0, 0, 0};
+
+    /* By default process terminates when writting to a
+     * pipe with no readers.
+     * Ignore SIGPIPE
+     */
+    AcrSigIgnore(SIGPIPE);
+    if (limit != 0 && limit->timeout == 0)
+        detach = 1;
+    /* Create signaling pipe that is used both for reporting the
+     * failed exec and syncing with exec.
+     */
+    if ((rc = AcrPipePair(&pipes[PIPE_SIGERR], ACR_PIPE_FULL_BLOCK)))
+        goto cleanup;
+    if (detach) {
+        /* In case of daemon process, create a signaling pipe that is used
+         * for reporting the granchild's pid to the parent.
+         */
+        if ((rc = AcrPipePair(&pipes[PIPE_SIGPID], ACR_PIPE_FULL_BLOCK)))
+            goto cleanup;
+    }
+    else {
+        if (inp != 0 && inp->buf != 0 && inp->len != 0) {
+            if ((rc = AcrPipePair(&pipes[PIPE_STDINP], ACR_PIPE_READ_BLOCK)))
+                goto cleanup;
+            ibuf.buf = inp->buf;
+            ibuf.len = inp->len;
+        }
+        if (out != 0) {
+            if ((rc = AcrPipePair(&pipes[PIPE_STDOUT], ACR_PIPE_WRITE_BLOCK)))
+                goto cleanup;
+            if ((rc = AcrSbInitAuto(&obuf_s, PROC_BUFFER_SIZE)))
+                goto cleanup;
+            obuf = &obuf_s;
+        }
+        if (err != 0 && err != out) {
+            if ((rc = AcrPipePair(&pipes[PIPE_STDERR], ACR_PIPE_WRITE_BLOCK)))
+                goto cleanup;
+            if ((rc = AcrSbInitAuto(&ebuf_s, PROC_BUFFER_SIZE)))
+                goto cleanup;
+            ebuf = &ebuf_s;
+        }
+    }
+    pid = fork();
+    if (pid < 0) {
+        rc = ACR_GET_OS_ERROR();
+        goto cleanup;
+    }
+    else if (pid == 0) {
+        /* Child process */
+
+        /* Close child side of pipes
+         */
+        i_close(&pipes[PIPE_STDINP_WRS]);
+        i_close(&pipes[PIPE_STDOUT_RDS]);
+        i_close(&pipes[PIPE_STDERR_RDS]);
+        i_close(&pipes[PIPE_SIGERR_RDS]);
+        i_close(&pipes[PIPE_SIGPID_RDS]);
+
+        /* Make sure the signaling pipes are closed on exec.
+         * This forces parent to wait until actual
+         * exec is performed or until the error is
+         * written to the signal pipe.
+         * In case of detached process the close
+         */
+        if (!detach) {
+            AcrCloseOnExec(pipes[PIPE_SIGERR_WRS], 1);
+            AcrCloseOnExec(pipes[PIPE_SIGPID_WRS], 1);
+        }
+
+        if (IS_VALID_STR(workdir) && chdir(workdir) == -1) {
+            /* Failed changing the current directoty */
+            rc = ACR_GET_OS_ERROR();
+            goto child_cleanup;
+        }
+        /* Set the real os SIGCHLD child handler.
+         */
+        AcrSigDefault(SIGCHLD);
+
+        close(STDIN_FILENO);
+        if (pipes[PIPE_STDINP_RDS] == -1) {
+            /* Redirect stdin to /dev/null
+             */
+            pipes[PIPE_STDINP_RDS] = AcrNullPipe(O_RDONLY, -1);
+            if (pipes[PIPE_STDINP_RDS] == -1) {
+                rc = ACR_GET_OS_ERROR();
+                goto child_cleanup;
+            }
+        }
+        if (dup2(pipes[PIPE_STDINP_RDS], STDIN_FILENO) == -1) {
+            rc = ACR_GET_OS_ERROR();
+            goto child_cleanup;
+        }
+        i_close(&pipes[PIPE_STDINP_RDS]);
+
+        close(STDOUT_FILENO);
+        close(STDERR_FILENO);
+        if (pipes[PIPE_STDOUT_WRS] == -1) {
+            /* Redirect stdout to /dev/null
+             */
+            pipes[PIPE_STDOUT_WRS] = AcrNullPipe(O_WRONLY, -1);
+            if (pipes[PIPE_STDOUT_WRS] == -1) {
+                rc = ACR_GET_OS_ERROR();
+                goto child_cleanup;
+            }
+        }
+        if (dup2(pipes[PIPE_STDOUT_WRS], STDOUT_FILENO) == -1) {
+            rc = ACR_GET_OS_ERROR();
+            goto child_cleanup;
+        }
+        if (pipes[PIPE_STDERR_WRS] == -1) {
+            if (out == 0) {
+                pipes[PIPE_STDERR_WRS] = AcrNullPipe(O_WRONLY, -1);
+                if (pipes[PIPE_STDERR_WRS] == -1) {
+                    rc = ACR_GET_OS_ERROR();
+                    goto child_cleanup;
+                }
+            }
+            else
+                pipes[PIPE_STDERR_WRS] = pipes[PIPE_STDOUT_WRS];
+        }
+        if (dup2(pipes[PIPE_STDERR_WRS], STDERR_FILENO) == -1) {
+            rc = ACR_GET_OS_ERROR();
+            goto child_cleanup;
+        }
+        if (pipes[PIPE_STDERR_WRS] != pipes[PIPE_STDOUT_WRS])
+            i_close(&pipes[PIPE_STDERR_WRS]);
+        i_close(&pipes[PIPE_STDOUT_WRS]);
+        /* Close all descriptors except our pipes
+         * using fdwalk
+         */
+        AcrFdwalk(_fdwalker, pipes);
+
+        if ((rc = _setplimit(limit)) != 0)
+            goto child_cleanup;
+        if (detach) {
+            /* Time to do detach the process.
+             */
+
+            /* Should this be configurable ?
+             */
+            umask(0077);
+
+            if (IS_EMPTY_STR(workdir) && chdir("/") == -1) {
+                rc = ACR_GET_OS_ERROR();
+                goto child_cleanup;
+            }
+            /* Second fork
+             */
+            pid = fork();
+            if (pid < 0) {
+                /* Second fork failed.
+                 * Time to bail out
+                 */
+                rc = ACR_GET_OS_ERROR();
+                goto child_cleanup;
+            }
+            else if (pid == 0) {
+                /* We are inside grand child process
+                 */
+                AcrCloseOnExec(pipes[PIPE_SIGERR_WRS], 1);
+                AcrCloseOnExec(pipes[PIPE_SIGPID_WRS], 1);
+
+                if (setsid() == -1) {
+                    rc = ACR_GET_OS_ERROR();
+                    goto child_cleanup;
+                }
+                /* Setup daemon signaling.
+                 */
+                AcrSigIgnore(SIGPIPE);
+                AcrSigIgnore(SIGTTOU);
+                AcrSigIgnore(SIGTTIN);
+                AcrSigIgnore(SIGTSTP);
+
+                /* Report our pid to the parent
+                 */
+                pid = getpid();
+                f_write(pipes[PIPE_SIGPID_WRS], &pid, sizeof(pid_t));
+            }
+            else {
+                /* We are done with the master child.
+                 */
+                exit(0);
+            }
+        }
+        if (envp != 0)
+            execve(executable, argv, envp);
+        else
+            execv(executable,  argv);
+        rc = ACR_GET_OS_ERROR();
+
+child_cleanup:
+        /* Still here?
+         */
+        f_write(pipes[PIPE_SIGERR_WRS], &rc, sizeof(int));
+        /* Alternative to exit() could be
+         * kill(info.pid, 9);
+         */
+        exit(0x80 + rc);
+    }
+    else {
+        /* Parent process */
+        struct pollfd ps[3];
+        char   buf[PROC_BUFFER_SIZE];
+        int    npipes     = 0;
+        int    pipelining = 1;
+        pid_t  child      = pid;
+        int    polltime   = -1;
+        acr_time_t endat  = 0;
+        ssize_t   rd, wr;
+        /* Close parent side of pipes
+         */
+        i_close(&pipes[PIPE_STDINP_RDS]);
+        i_close(&pipes[PIPE_STDOUT_WRS]);
+        i_close(&pipes[PIPE_STDERR_WRS]);
+        i_close(&pipes[PIPE_SIGERR_WRS]);
+        i_close(&pipes[PIPE_SIGPID_WRS]);
+/*
+        if (limit != 0 && limit->timeout > 0) {
+            endat = AcrTimeNow() + AcrTimeFromMsec(limit->timeout);
+            polltime = PROC_TIMEOUT_STEP;
+        }
+*/
+        if (pipes[PIPE_STDINP_WRS] == -1 &&
+            pipes[PIPE_STDOUT_RDS] == -1 &&
+            pipes[PIPE_STDERR_RDS] == -1)
+            pipelining = 0;
+        /* Handshake with the child process.
+         * If the read is sucessful it means that
+         * either init or execv inside child failed.
+         * However in case of detached proces this
+         * is valid struct informing about grandchild pid.
+         */
+        rd = r_read(pipes[PIPE_SIGERR_RDS], &sigerr, sizeof(int));
+        i_close(&pipes[PIPE_SIGERR_RDS]);
+        if (rd == sizeof(int)) {
+            /* We have received error status
+             * from the child
+             */
+            pipelining = 0;
+        }
+        else {
+            /* Guard againts partial reads */
+            sigerr = 0;
+        }
+        if (detach) {
+            rd = r_read(pipes[PIPE_SIGPID_RDS], &sigpid, sizeof(pid_t));
+            i_close(&pipes[PIPE_SIGPID_RDS]);
+            if (rd == sizeof(pid_t)) {
+                /* We have received the grand child's pid.
+                 */
+                pipelining = 0;
+            }
+            else {
+                /* Guard againts partial reads */
+                sigpid = 0;
+            }
+        }
+        while (pipelining) {
+            npipes = 0;
+            if (pipes[PIPE_STDINP_WRS] != -1) {
+                ps[npipes].fd = pipes[PIPE_STDINP_WRS];
+                ps[npipes].events  = POLLOUT;
+                ps[npipes].revents = 0;
+                npipes++;
+            }
+            if (pipes[PIPE_STDOUT_RDS] != -1) {
+                ps[npipes].fd = pipes[PIPE_STDOUT_RDS];
+                ps[npipes].events  = POLLIN;
+                ps[npipes].revents = 0;
+                npipes++;
+            }
+            if (pipes[PIPE_STDERR_RDS] != -1) {
+                ps[npipes].fd = pipes[PIPE_STDERR_RDS];
+                ps[npipes].events  = POLLIN;
+                ps[npipes].revents = 0;
+                npipes++;
+            }
+            if (npipes) {
+                do {
+                    rc = poll(ps, npipes, polltime);
+                } while (rc == -1 && errno == EINTR);
+                if (rc < 1) {
+                    if (polltime == -1 || rc == -1)
+                        break;
+                    /* No events fired within PROC_TIMEOUT_STEP.
+                     * Check if we reached the abolute
+                     */
+                    if (AcrTimeNow() < endat)
+                        continue;
+                    /* Send SIGTERM to the child
+                     */
+                    kill(pid, SIGTERM);
+                    break;
+                }
+                for (i = 0; i < npipes; i++) {
+                    /* Loop trough every pollfd and check for the
+                     * returned events.
+                     */
+                    if (pipes[PIPE_STDINP_WRS] == ps[i].fd && ps[i].revents) {
+                        wr = 0;
+                        if (ps[i].revents & POLLOUT) {
+                            wr = r_write(pipes[PIPE_STDINP_WRS],
+                                         ibuf.buf + ibuf.use,
+                                         ibuf.len - ibuf.use);
+                        }
+                        if (wr > 0) {
+                            ibuf.use += (int)wr;
+                            if (ibuf.len == ibuf.use) {
+                                /* Closing the stdin should cause
+                                 * EOF in the child.
+                                 */
+                                i_close(&pipes[PIPE_STDINP_WRS]);
+                            }
+                        }
+                        else {
+                            if (wr != -1 || !ACR_STATUS_IS_EAGAIN(errno))
+                                i_close(&pipes[PIPE_STDINP_WRS]);
+                        }
+                    }
+                    if (pipes[PIPE_STDOUT_RDS] == ps[i].fd && ps[i].revents) {
+                        rd = 0;
+                        if (ps[i].revents & POLLIN) {
+                            rd = r_read(pipes[PIPE_STDOUT_RDS],
+                                        buf, PROC_BUFFER_SIZE);
+                        }
+                        if (rd > 0) {
+                            if (AcrSbCatb(obuf, buf, rd)) {
+                                /* Error appending to the buffer.
+                                 * We have probably reach the limit or ENOMEM
+                                 */
+                                pipelining = 0;
+                                break;
+                            }
+                            if (ps[i].revents & POLLHUP)
+                                i_close(&pipes[PIPE_STDERR_RDS]);
+                        }
+                        else {
+                            if (rd != -1 || !ACR_STATUS_IS_EAGAIN(errno))
+                                i_close(&pipes[PIPE_STDOUT_RDS]);
+                        }
+                    }
+                    if (pipes[PIPE_STDERR_RDS] == ps[i].fd && ps[i].revents) {
+                        rd = 0;
+                        if (ps[i].revents & POLLIN) {
+                            rd = r_read(pipes[PIPE_STDERR_RDS],
+                                        buf, PROC_BUFFER_SIZE);
+                        }
+                        if (rd > 0) {
+                            if (AcrSbCatb(ebuf, buf, rd)) {
+                                /* Error appending to the buffer.
+                                 * We have probably reach the limit or ENOMEM
+                                 */
+                                pipelining = 0;
+                                break;
+                            }
+                            if (ps[i].revents & POLLHUP)
+                                i_close(&pipes[PIPE_STDERR_RDS]);
+                        }
+                        else {
+                            if (rd != -1 || !ACR_STATUS_IS_EAGAIN(errno))
+                                i_close(&pipes[PIPE_STDERR_RDS]);
+                        }
+                    }
+                }
+            }
+            else {
+                /* All pipes are closed
+                 */
+                pipelining = 0;
+            }
+        }
+
+        /* Finished child stream processing.
+         * Cleanup pipes.
+         */
+        i_close(&pipes[PIPE_STDINP_WRS]);
+        i_close(&pipes[PIPE_STDOUT_RDS]);
+        i_close(&pipes[PIPE_STDERR_RDS]);
+
+        do {
+            /* TODO: We should consider using timeout here as well
+             *       if set, instead infinite wait.
+             */
+            child = waitpid(pid, &exitval, WUNTRACED);
+        } while (child == -1 && errno == EINTR);
+
+        if (sigerr) {
+            /* Error reported from child
+             */
+            exitwhy = ACR_CHILD_ERROR;
+            exitval = sigerr;
+            goto finished;
+        }
+        if (detach) {
+            if (sigpid) {
+                /* We have a pid from the grand child
+                 */
+                exitwhy = ACR_CHILD_DONE;
+                exitval = sigpid;
+            }
+            else {
+                /* We didn't recive the valid grandchild's pid
+                 * XXX: Check for a valid return value
+                 */
+                exitwhy = ACR_CHILD_ERROR;
+                exitval = child;
+            }
+            goto finished;
+        }
+        switch (child) {
+            case 0:
+                /* Unexpected condition
+                 */
+                exitwhy = ACR_CHILD_NOTDONE;
+                exitval = 0;
+            break;
+            case -1:
+                /* unexpected condition */
+                exitwhy = ACR_CHILD_NOTDONE;
+                exitval = ACR_GET_OS_ERROR();
+            break;
+            default:
+                if (WIFEXITED(exitval)) {
+                    exitwhy = ACR_CHILD_DONE;
+                    exitval = WEXITSTATUS(exitval);
+                }
+                else if (WIFSIGNALED(exitval)) {
+                    exitwhy = ACR_CHILD_SIGNAL;
+#ifdef WCOREDUMP
+                    if (WCOREDUMP(exitval))
+                        exitwhy = ACR_CHILD_SIGNAL_CORE;
+#endif
+                    exitval = WTERMSIG(exitval);
+                }
+                else {
+                    /* unexpected condition */
+                    exitwhy = ACR_CHILD_ERROR;
+                    exitval = child;
+                }
+            break;
+        }
+    }
+
+finished:
+    AcrSigDefault(SIGPIPE);
+    if (obuf != 0) {
+        AcrSbPutb(obuf, 0);
+        AcrSbPutb(obuf, 0);
+        out->len = AcrSbLen(obuf);
+        out->buf = AcrSbDetach(obuf);
+    }
+    if (ebuf != 0) {
+        AcrSbPutb(ebuf, 0);
+        AcrSbPutb(ebuf, 0);
+        err->len = AcrSbLen(ebuf);
+        err->buf = AcrSbDetach(ebuf);
+    }
+    if (inp != 0)
+        inp->use = ibuf.use;
+    *retval = exitval;
+    return exitwhy;
+
+cleanup:
+    AcrSbFree(obuf);
+    AcrSbFree(ebuf);
+    for (i = 0; i < PIPE_COUNT; i++)
+        s_close(pipes[i]);
+    AcrSigDefault(SIGPIPE);
+    *retval = rc;
+    return ACR_PARENT_ERROR;
+}
+
+ACR_JNI_EXPORT(jobject, ExecImpl, init0)(JNI_STDARGS)
+{
+    if (_clazzn.u == 1)
+        return (*env)->NewObject(env, _clazzn.i, J4MID(0000));
+    if (AcrLoadClass(env, &_clazzn, 0) != 0)
+        return 0;
+    R_LOAD_METHOD(0000, 0);
+    _clazzn.u = 1;
+    return (*env)->NewObject(env, _clazzn.i, J4MID(0000));
+}
+

Propchange: commons/sandbox/runtime/trunk/src/main/native/os/unix/exec.c
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: commons/sandbox/runtime/trunk/src/main/native/os/unix/util.c
URL: http://svn.apache.org/viewvc/commons/sandbox/runtime/trunk/src/main/native/os/unix/util.c?rev=1097056&r1=1097055&r2=1097056&view=diff
==============================================================================
--- commons/sandbox/runtime/trunk/src/main/native/os/unix/util.c (original)
+++ commons/sandbox/runtime/trunk/src/main/native/os/unix/util.c Wed Apr 27 09:48:53 2011
@@ -21,6 +21,91 @@
 #include "arch_opts.h"
 #include <poll.h>
 
+#if HAVE_FDWALK
+int AcrFdwalk(int (*func)(void *data , int fd), void *cd)
+{
+    return fdwalk(func, cd);
+}
+
+#else
+# if defined(_LINUX)
+#  include <dirent.h>
+#  define PROCFS_SELF_FD  "/proc/self/fd"
+
+int AcrFdwalk(int (*func)(void *data , int fd), void *cd)
+{
+    DIR           *pd;
+    struct dirent *pe;
+    int            rc = 0;
+    int            se;
+    if (!(pd = opendir(PROCFS_SELF_FD)))
+        return -1;
+
+    while ((pe = readdir(pd))) {
+        int   fd;
+        long  fv;
+        char *ep;
+        if (*pe->d_name == '.')
+            continue;
+        /* To distinguish success/failure after strtol call
+         */
+        errno = 0;
+        fv = strtol(pe->d_name, &ep, 10);
+        /* Check for various possible errors */
+        if ((errno == ERANGE && (fv == LONG_MAX || fv == LONG_MIN)) ||
+            (errno != 0 && fv == 0) ||
+            (errno != 0 || !ep || *ep)) {
+            /* Not an numbered entry.
+             */
+            continue;
+        }
+        if (fv < 0 || fv > INT_MAX)
+            continue;
+        else
+            fd = (int)fv;
+        if (fd == dirfd(pd))
+            continue;
+        if ((rc = (*func)(cd, fd)))
+            break;
+    }
+    if (rc)
+        se = errno;
+    closedir(pd);
+    if (rc)
+        errno = se;
+    return rc;
+}
+
+# else
+#  if HAVE_SYS_RESOURCE_H
+#   include <sys/resource.h>
+#  endif
+int AcrFdwalk(int (*func)(void *, int), void *cd)
+{
+    int rc = 0;
+    int fd;
+    int fm = 1024;
+#  if HAVE_SYS_RESOURCE_H
+    struct rlimit rl;
+
+    if (getrlimit(RLIMIT_NOFILE, &rl) == 0 && rl.rlim_max != RLIM_INFINITY)
+        fm = (int)rl.rlim_max;
+    else
+#  else
+        fm = sysconf(_SC_OPEN_MAX);
+#  endif
+
+    for (fd = 0; fd < fm; fd++) {
+        errno = 0;
+        rc = (*func)(cd, fd);
+        if (rc && errno != ENOENT && errno != EBADF)
+            break;
+    }
+    return rc;
+}
+# endif /* _LINUX       */
+#endif  /* HAVE_FDWALK  */
+
 int
 AcrNonblock(int fd, int on)
 {
@@ -211,3 +296,89 @@ finally:
 
     return rc;
 }
+
+#if defined(__NETBSD) || defined(__DARWIN)
+static void avoid_zombies(int signo)
+{
+    int exit_status;
+
+    while (waitpid(-1, &exit_status, WNOHANG) > 0) {
+        /* do nothing */
+    }
+}
+#endif /* DARWIN */
+
+int AcrSigIgnore(int signo)
+{
+    int rc = -1;
+    struct sigaction act, oact;
+
+    if (signo <= 0 || signo >= NSIG) {
+        return EINVAL;
+    }
+    memset(&act, 0, sizeof(struct sigaction));
+
+    sigemptyset(&act.sa_mask);
+    act.sa_handler = SIG_IGN;
+    act.sa_flags   = 0;
+#ifdef SA_INTERRUPT             /* SunOS */
+    act.sa_flags |= SA_INTERRUPT;
+#endif
+    if (signo != SIGALRM)
+        act.sa_flags |= SA_RESTART;
+#ifdef SA_NOCLDSTOP
+    if (signo == SIGCHLD)
+        act.sa_flags |= SA_NOCLDSTOP;
+#endif
+#ifdef SA_NOCLDWAIT
+    if (signo == SIGCHLD)
+        act.sa_flags |= SA_NOCLDWAIT;
+#endif
+#if defined(__NETBSD) || defined(__DARWIN)
+    /* ignoring SIGCHLD or leaving the default disposition doesn't avoid zombies,
+     * and there is no SA_NOCLDWAIT flag, so catch the signal and reap status in
+     * the handler to avoid zombies
+    */
+    if (signo == SIGCHLD) {
+        act.sa_handler = avoid_zombies;
+    }
+#endif
+    rc = sigaction(signo, &act, &oact);
+    if (rc < 0)
+        return errno;
+    else
+        return 0;
+}
+
+int AcrSigDefault(int signo)
+{
+    int rc = -1;
+    struct sigaction act, oact;
+
+    if (signo <= 0 || signo >= NSIG) {
+        return EINVAL;
+    }
+    memset(&act, 0, sizeof(struct sigaction));
+
+    sigemptyset(&act.sa_mask);
+    act.sa_handler = SIG_DFL;
+    act.sa_flags   = 0;
+#ifdef SA_INTERRUPT             /* SunOS */
+    act.sa_flags |= SA_INTERRUPT;
+#endif
+    if (signo != SIGALRM)
+        act.sa_flags |= SA_RESTART;
+#ifdef SA_NOCLDSTOP
+    if (signo == SIGCHLD)
+        act.sa_flags |= SA_NOCLDSTOP;
+#endif
+#ifdef SA_NOCLDWAIT
+    if (signo == SIGCHLD)
+        act.sa_flags |= SA_NOCLDWAIT;
+#endif
+    rc = sigaction(signo, &act, &oact);
+    if (rc < 0)
+        return errno;
+    else
+        return 0;
+}

Modified: commons/sandbox/runtime/trunk/src/main/native/shared/string.c
URL: http://svn.apache.org/viewvc/commons/sandbox/runtime/trunk/src/main/native/shared/string.c?rev=1097056&r1=1097055&r2=1097056&view=diff
==============================================================================
--- commons/sandbox/runtime/trunk/src/main/native/shared/string.c (original)
+++ commons/sandbox/runtime/trunk/src/main/native/shared/string.c Wed Apr 27 09:48:53 2011
@@ -1055,6 +1055,72 @@ AcrNewJavaStringU(JNIEnv *env, const cha
         return new_string_utf_8(env, str);
 }
 
+void AcrFreeStringArray(void **arr)
+{
+    if (arr != 0) {
+        void **ap = arr;
+        while (*ap != 0) {
+            AcrFree(*ap);
+            ap++;
+        }
+        AcrFree(arr);
+    }
+}
+
+char **
+AcrGetJavaStringArrayA(JNI_STDENV, jobjectArray arr)
+{
+    char **ret = NULL;
+    jsize  cnt;
+    jsize  i;
+
+    if (arr == 0)
+        return 0;
+
+    cnt = (*env)->GetArrayLength(env, arr);
+    ret = ACR_MALLOC(char *, cnt + 1);
+    if (ret == 0)
+        return 0;
+    for (i = 0; i < cnt; i++) {
+        jstring str = (*env)->GetObjectArrayElement(env, arr, i);
+        if (str != 0) {
+            ret[i] = AcrGetJavaStringA(env, str, 0);
+            (*env)->DeleteLocalRef(env, str);
+        }
+        else
+            break;
+    }
+    ret[i] = 0;
+    return ret;
+}
+
+wchar_t **
+AcrGetJavaStringArrayW(JNI_STDENV, jobjectArray arr)
+{
+    wchar_t **ret = NULL;
+    jsize  cnt;
+    jsize  i;
+
+    if (arr == 0)
+        return 0;
+
+    cnt = (*env)->GetArrayLength(env, arr);
+    ret = (wchar_t **)ACR_MALLOC(wchar_t *, cnt + 1);
+    if (ret == 0)
+        return 0;
+    for (i = 0; i < cnt; i++) {
+        jstring str = (*env)->GetObjectArrayElement(env, arr, i);
+        if (str) {
+            ret[i] = AcrGetJavaStringW(env, str, 0);
+            (*env)->DeleteLocalRef(env, str);
+        }
+        else
+            break;
+    }
+    ret[i] = 0;
+    return ret;
+}
+
 #if defined(ENABLE_TEST_PRIVATE)
 
 ACR_JNI_EXPORT(jint, TestString, test0)(JNI_STDARGS, jstring s)