Merged gcj-eclipse branch to trunk.

From-SVN: r120621
This commit is contained in:
Tom Tromey 2007-01-09 19:58:05 +00:00
parent c648dedbde
commit 97b8365caf
17478 changed files with 606493 additions and 100744 deletions

View file

@ -38,7 +38,7 @@ exception statement from your version. */
#include <config.h>
#include "java_lang_VMProcess.h"
#include "gnu_java_nio_channels_FileChannelImpl.h"
#include "gnu_java_nio_FileChannelImpl.h"
#include <sys/types.h>
#include <sys/wait.h>
@ -50,10 +50,8 @@ exception statement from your version. */
#include <fcntl.h>
#include <stdio.h>
#include <jcl.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);
@ -65,7 +63,6 @@ static char *copy_elem (JNIEnv * env, jobject stringArray, jint i);
static char *
copy_string (JNIEnv * env, jobject string)
{
char errbuf[64];
const char *utf;
jclass clazz;
char *copy;
@ -89,12 +86,10 @@ copy_string (JNIEnv * env, jobject string)
/* 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);
}
@ -131,8 +126,8 @@ Java_java_lang_VMProcess_nativeSpawn (JNIEnv * env, jobject this,
jobjectArray envArray, jobject dirFile,
jboolean redirect)
{
int fds[3][2] = { {-1, -1}, {-1, -1}, {-1, -1} };
jobject streams[3] = { NULL, NULL, NULL };
int fds[CPIO_EXEC_NUM_PIPES];
jobject streams[CPIO_EXEC_NUM_PIPES] = { NULL, NULL, NULL };
jobject dirString = NULL;
char **newEnviron = NULL;
jsize cmdArrayLen = 0;
@ -142,10 +137,11 @@ Java_java_lang_VMProcess_nativeSpawn (JNIEnv * env, jobject this,
char *dir = NULL;
pid_t pid = -1;
char errbuf[64];
jmethodID method;
jclass clazz;
jmethodID method, vmmethod;
jclass clazz, vmclazz;
int i;
int pipe_count = redirect ? 2 : 3;
int err;
/* Check for null */
if (cmdArray == NULL)
@ -182,9 +178,7 @@ Java_java_lang_VMProcess_nativeSpawn (JNIEnv * env, jobject this,
+ (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;
}
@ -209,125 +203,43 @@ Java_java_lang_VMProcess_nativeSpawn (JNIEnv * env, jobject this,
{
if ((dir = copy_string (env, dirString)) == NULL)
goto done;
strings[num_strings++] = dir;
}
/* Create inter-process pipes */
for (i = 0; i < pipe_count; i++)
err = cpproc_forkAndExec(strings, newEnviron, fds, pipe_count, &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);
if (pipe_count == 3)
(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 (pipe_count == 2)
{
/* Duplicate stdout to stderr. */
if (dup2 (1, 2) == -1)
{
fprintf (stderr, "dup2: %s", strerror (errno));
exit (127);
}
}
else 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");
vmclazz = (*env)->FindClass (env, "gnu/java/nio/VMChannel");
clazz = (*env)->FindClass (env, "gnu/java/nio/FileChannelImpl");
if ((*env)->ExceptionOccurred (env))
goto done;
method = (*env)->GetMethodID (env, clazz, "<init>", "(II)V");
vmmethod = (*env)->GetMethodID (env, vmclazz, "<init>", "(I)V");
method = (*env)->GetMethodID (env, clazz, "<init>", "(Lgnu/java/nio/VMChannel;I)V");
if ((*env)->ExceptionOccurred (env))
goto done;
for (i = 0; i < pipe_count; 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)
? gnu_java_nio_channels_FileChannelImpl_WRITE
: gnu_java_nio_channels_FileChannelImpl_READ);
const int fd = fds[i];
const int mode = ((i == CPIO_EXEC_STDIN) ? 2 : 1);
jclass sclazz;
jmethodID smethod;
jobject channel = (*env)->NewObject (env, clazz, method, fd, mode);
jobject vmchannel;
jobject channel;
vmchannel = (*env)->NewObject (env, vmclazz, vmmethod, fd);
if ((*env)->ExceptionOccurred (env))
goto done;
channel = (*env)->NewObject (env, clazz, method, vmchannel, mode);
if ((*env)->ExceptionOccurred (env))
goto done;
if (mode == gnu_java_nio_channels_FileChannelImpl_WRITE)
if (mode == gnu_java_nio_FileChannelImpl_WRITE)
sclazz = (*env)->FindClass (env, "java/io/FileOutputStream");
else
sclazz = (*env)->FindClass (env, "java/io/FileInputStream");
@ -335,7 +247,7 @@ Java_java_lang_VMProcess_nativeSpawn (JNIEnv * env, jobject this,
goto done;
smethod = (*env)->GetMethodID (env, sclazz, "<init>",
"(Lgnu/java/nio/channels/FileChannelImpl;)V");
"(Lgnu/java/nio/FileChannelImpl;)V");
if ((*env)->ExceptionOccurred (env))
goto done;
@ -355,7 +267,10 @@ Java_java_lang_VMProcess_nativeSpawn (JNIEnv * env, jobject this,
if ((*env)->ExceptionOccurred (env))
goto done;
(*env)->CallVoidMethod (env, this, method,
streams[0], streams[1], streams[2], (jlong) pid);
streams[CPIO_EXEC_STDIN],
streams[CPIO_EXEC_STDOUT],
streams[CPIO_EXEC_STDERR],
(jlong) pid);
if ((*env)->ExceptionOccurred (env))
goto done;
@ -365,15 +280,6 @@ done:
* parent process. Our goal is to clean up the mess we created.
*/
/* Close child's ends of pipes */
for (i = 0; i < pipe_count; 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
@ -382,7 +288,7 @@ done:
*/
for (i = 0; i < pipe_count; i++)
{
const int fd = fds[i][i == 0];
const int fd = fds[i];
if (fd != -1 && streams[i] == NULL)
close (fd);
@ -392,7 +298,8 @@ done:
while (num_strings > 0)
free (strings[--num_strings]);
free (strings);
if (dir != NULL)
free(dir);
/* Done */
return;
@ -431,19 +338,20 @@ Java_java_lang_VMProcess_nativeReap (JNIEnv * env, jclass clazz)
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(errno));
clazz = (*env)->FindClass (env, "java/lang/InternalError");
if ((*env)->ExceptionOccurred (env))
return JNI_FALSE;
@ -485,12 +393,13 @@ JNIEXPORT void JNICALL
Java_java_lang_VMProcess_nativeKill (JNIEnv * env, jclass clazz, jlong pid)
{
char ebuf[64];
if (kill ((pid_t) pid, SIGKILL) == -1)
int err;
err = cpproc_kill((pid_t) pid, SIGKILL);
if (err != 0)
{
TARGET_NATIVE_MISC_FORMAT_STRING2 (ebuf,
sizeof (ebuf), "kill(%ld): %s",
(long) pid, strerror (errno));
snprintf (ebuf, sizeof (ebuf), "kill(%ld): %s",
(long) pid, cpnative_getErrorString (err));
clazz = (*env)->FindClass (env, "java/lang/InternalError");
if ((*env)->ExceptionOccurred (env))
return;