Hi,

Here is a patch which modifies the code repartition relatively to process handling. The native layer code is still missing but it will be straightforward to add it again from the previous code after this cleanup. It looks like there is a memory leak also in that code (relatively to the dir variable)

Regards,
Guilhem.

ChangeLog entry:
2006-02-18  Guilhem Lavaux  <[EMAIL PROTECTED]>

        * native/jni/java-lang/java_lang_VMProcess.c: Removed TARGET
        dependency. Simplified the JNI code by moving some part into the
        native layer.

* native/jni/native-lib/cpproc.h: New interface to handle processes.


Index: native/jni/java-lang/java_lang_VMProcess.c
===================================================================
RCS file: 
/cvsroot/classpath/classpath/native/jni/java-lang/java_lang_VMProcess.c,v
retrieving revision 1.7
diff -u -r1.7 java_lang_VMProcess.c
--- native/jni/java-lang/java_lang_VMProcess.c  12 Oct 2005 11:39:05 -0000      
1.7
+++ native/jni/java-lang/java_lang_VMProcess.c  18 Feb 2006 21:20:12 -0000
@@ -48,8 +48,8 @@
 #include <fcntl.h>
 #include <stdio.h>
 
-#include "target_native.h"
-#include "target_native_misc.h"
+#include "cpnative.h"
+#include "cpproc.h"
 
 /* Internal functions */
 static char *copy_string (JNIEnv * env, jobject string);
@@ -72,7 +72,6 @@
 static char *
 copy_string (JNIEnv * env, jobject string)
 {
-  char errbuf[64];
   const char *utf;
   jclass clazz;
   char *copy;
@@ -96,12 +95,10 @@
   /* Copy it */
   if ((copy = strdup (utf)) == NULL)
     {
-      TARGET_NATIVE_MISC_FORMAT_STRING1 (errbuf, sizeof (errbuf),
-                                        "strdup: %s", strerror (errno));
       clazz = (*env)->FindClass (env, "java/lang/InternalError");
       if ((*env)->ExceptionOccurred (env))
        return NULL;
-      (*env)->ThrowNew (env, clazz, errbuf);
+      (*env)->ThrowNew (env, clazz, "strdup returned NULL");
       (*env)->DeleteLocalRef (env, clazz);
     }
 
@@ -137,7 +134,7 @@
                                      jobjectArray cmdArray,
                                      jobjectArray envArray, jobject dirFile)
 {
-  int fds[3][2] = { {-1, -1}, {-1, -1}, {-1, -1} };
+  int fds[3];
   jobject streams[3] = { NULL, NULL, NULL };
   jobject dirString = NULL;
   char **newEnviron = NULL;
@@ -151,6 +148,7 @@
   jmethodID method;
   jclass clazz;
   int i;
+  int err;
 
   /* Check for null */
   if (cmdArray == NULL)
@@ -187,9 +185,7 @@
                          + (dirString !=
                             NULL ? 1 : 0)) * sizeof (*strings))) == NULL)
     {
-      TARGET_NATIVE_MISC_FORMAT_STRING1 (errbuf,
-                                        sizeof (errbuf), "malloc: %s",
-                                        strerror (errno));
+      strncpy (errbuf, "malloc failed", sizeof(errbuf));
       goto out_of_memory;
     }
 
@@ -214,93 +210,15 @@
     {
       if ((dir = copy_string (env, dirString)) == NULL)
        goto done;
-      strings[num_strings++] = dir;
     }
 
-  /* Create inter-process pipes */
-  for (i = 0; i < 3; i++)
+  err = cpproc_forkAndExec(strings, newEnviron, fds, &pid, dir);
+  if (err != 0)
     {
-      if (pipe (fds[i]) == -1)
-       {
-         TARGET_NATIVE_MISC_FORMAT_STRING1 (errbuf,
-                                            sizeof (errbuf), "pipe: %s",
-                                            strerror (errno));
-         goto system_error;
-       }
-    }
-
-  /* Set close-on-exec flag for parent's ends of pipes */
-  (void) fcntl (fds[0][1], F_SETFD, 1);
-  (void) fcntl (fds[1][0], F_SETFD, 1);
-  (void) fcntl (fds[2][0], F_SETFD, 1);
-
-  /* Fork into parent and child processes */
-  if ((pid = fork ()) == (pid_t) - 1)
-    {
-      TARGET_NATIVE_MISC_FORMAT_STRING1 (errbuf,
-                                        sizeof (errbuf), "fork: %s",
-                                        strerror (errno));
+      strncpy(errbuf, cpnative_getErrorString (err), sizeof(errbuf));
       goto system_error;
     }
 
-  /* Child becomes the new process */
-  if (pid == 0)
-    {
-      char *const path = strings[0];
-
-      /* Move file descriptors to standard locations */
-      if (fds[0][0] != 0)
-       {
-         if (dup2 (fds[0][0], 0) == -1)
-           {
-             fprintf (stderr, "dup2: %s", strerror (errno));
-             exit (127);
-           }
-         close (fds[0][0]);
-       }
-      if (fds[1][1] != 1)
-       {
-         if (dup2 (fds[1][1], 1) == -1)
-           {
-             fprintf (stderr, "dup2: %s", strerror (errno));
-             exit (127);
-           }
-         close (fds[1][1]);
-       }
-      if (fds[2][1] != 2)
-       {
-         if (dup2 (fds[2][1], 2) == -1)
-           {
-             fprintf (stderr, "dup2: %s", strerror (errno));
-             exit (127);
-           }
-         close (fds[2][1]);
-       }
-
-      /* Change into destination directory */
-      if (dir != NULL && chdir (dir) == -1)
-       {
-         fprintf (stderr, "%s: %s", dir, strerror (errno));
-         exit (127);
-       }
-
-      /* Make argv[0] last component of executable pathname */
-      /* XXX should use "file.separator" property here XXX */
-      for (i = strlen (path); i > 0 && path[i - 1] != '/'; i--);
-      strings[0] = path + i;
-
-      /* Set new environment */
-      if (newEnviron != NULL)
-       environ = newEnviron;
-
-      /* Execute new program (this will close the parent end of the pipes) */
-      execvp (path, strings);
-
-      /* Failed */
-      fprintf (stderr, "%s: %s", path, strerror (errno));
-      exit (127);
-    }
-
   /* Create Input/OutputStream objects around parent file descriptors */
   clazz = (*env)->FindClass (env, "gnu/java/nio/channels/FileChannelImpl");
   if ((*env)->ExceptionOccurred (env))
@@ -311,8 +229,8 @@
   for (i = 0; i < 3; i++)
     {
       /* Mode is WRITE (2) for in and READ (1) for out and err. */
-      const int fd = fds[i][i == 0];
-      const int mode = (i == 0) ? 2 : 1;
+      const int fd = fds[i];
+      const int mode = (i == CPIO_EXEC_STDIN) ? 2 : 1;
       jclass sclazz;
       jmethodID smethod;
 
@@ -358,15 +276,6 @@
    * parent process. Our goal is to clean up the mess we created.
    */
 
-  /* Close child's ends of pipes */
-  for (i = 0; i < 3; i++)
-    {
-      const int fd = fds[i][i != 0];
-
-      if (fd != -1)
-       close (fd);
-    }
-
   /*
    * Close parent's ends of pipes if Input/OutputStreams never got created.
    * This can only happen in a failure case. If a Stream object
@@ -375,7 +284,7 @@
    */
   for (i = 0; i < 3; i++)
     {
-      const int fd = fds[i][i == 0];
+      const int fd = fds[i];
 
       if (fd != -1 && streams[i] == NULL)
        close (fd);
@@ -385,6 +294,8 @@
   while (num_strings > 0)
     free (strings[--num_strings]);
   free (strings);
+  if (dir != NULL)
+    free(dir);
 
   /* Done */
   return;
@@ -424,19 +335,21 @@
   jfieldID field;
   jint status;
   pid_t pid;
+  int err;
 
   /* Try to reap a child process, but don't block */
-  if ((pid = waitpid ((pid_t) - 1, &status, WNOHANG)) == 0)
+  err = cpproc_waitpid ((pid_t) -1, &status, &pid, WNOHANG);
+  if (err == 0 && pid == 0)
     return JNI_FALSE;
 
   /* Check result from waitpid() */
-  if (pid == (pid_t) - 1)
+  if (err != 0)
     {
-      if (errno == ECHILD || errno == EINTR)
+      if (err == ECHILD || err == EINTR)
        return JNI_FALSE;
-      TARGET_NATIVE_MISC_FORMAT_STRING2 (ebuf,
-                                        sizeof (ebuf), "waitpid(%ld): %s",
-                                        (long) pid, strerror (errno));
+      snprintf (ebuf, sizeof (ebuf), "waitpid(%ld): %s",
+               (long) pid, cpnative_getErrorString (err));
+
       clazz = (*env)->FindClass (env, "java/lang/InternalError");
       if ((*env)->ExceptionOccurred (env))
        return JNI_FALSE;
@@ -478,12 +391,15 @@
 Java_java_lang_VMProcess_nativeKill (JNIEnv * env, jclass clazz, jlong pid)
 {
   char ebuf[64];
+  int err;
 
-  if (kill ((pid_t) pid, SIGKILL) == -1)
-    {
-      TARGET_NATIVE_MISC_FORMAT_STRING2 (ebuf,
-                                        sizeof (ebuf), "kill(%ld): %s",
-                                        (long) pid, strerror (errno));
+  err = cpproc_kill ((pid_t) pid, SIGKILL);
+
+  if (err != 0)
+    {      
+      snprintf (ebuf,
+               sizeof (ebuf), "kill(%ld): %s",
+               (long) pid, cpnative_getErrorString (err));
       clazz = (*env)->FindClass (env, "java/lang/InternalError");
       if ((*env)->ExceptionOccurred (env))
        return;
Index: native/jni/native-lib/cpproc.h
===================================================================
RCS file: native/jni/native-lib/cpproc.h
diff -N native/jni/native-lib/cpproc.h
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ native/jni/native-lib/cpproc.h      18 Feb 2006 21:20:12 -0000
@@ -0,0 +1,50 @@
+/* cpproc.h -
+   Copyright (C) 2006  Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version. */
+#ifndef _CLASSPATH_PROC_H_INCLUDED
+#define _CLASSPATH_PROC_H_INCLUDED
+
+#include <sys/types.h>
+
+#define CPIO_EXEC_STDIN 0
+#define CPIO_EXEC_STDOUT 1
+#define CPIO_EXEC_STDERR 2
+
+JNIEXPORT int cpproc_forkAndExec (char * const *commandLine, char * const * 
newEnviron, int *fds, pid_t *pid, const char *wd);
+JNIEXPORT int cpproc_waitpid (pid_t pid, int *status, pid_t *outpid, int 
options);
+JNIEXPORT int cpproc_kill (pid_t pid, int signal);
+
+#endif

Reply via email to