/*
 * Java core library component.
 *
 * Copyright (c) 1997, 1998
 *      Transvirtual Technologies, Inc.  All rights reserved.
 *
 * See the file "license.terms" for information on usage and redistribution
 * of this file.
 */

package kaffe.lang;

import java.lang.String;
import java.io.FileDescriptor;
import java.io.FileOutputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

public class UNIXProcess
  extends Process
  implements Runnable
{
	boolean isalive;
	int exit_code;
	FileDescriptor stdin_fd;
	FileDescriptor stdout_fd;
	FileDescriptor stderr_fd;
	FileDescriptor sync_fd;
	int pid;
	OutputStream stdin_stream;
	InputStream raw_stdout;
	InputStream raw_stderr;
	int numReaders;		// what's that for?
	private static Thread tidy;

public UNIXProcess() {
}

public UNIXProcess(String argv[], String arge[]) {

	stdin_fd = new FileDescriptor();
	stdout_fd = new FileDescriptor();
	stderr_fd = new FileDescriptor();
	sync_fd = new FileDescriptor();

	/* We first create a thread to start the new process in.  This
	 * is because on some system we can only wait for the child from
	 * it's parent (UNIX for example).  So, we have to create a thread
	 * to do the waiting.
	 */
	final String _argv[] = argv;
	final String _arge[] = arge;
	Thread sitter = new Thread() {
		public void run() {
			if (forkAndExec(_argv, _arge) == 0) {
				synchronized(this) {
					isalive = true;
					notify();
				}
				exit_code = execWait();
			}
			synchronized(this) {
				isalive = false;
				notifyAll();
			}
			synchronized(UNIXProcess.this) {
				UNIXProcess.this.notifyAll();
			}
		}
	};

	/* Start the sitter then wait until it says it's child has started.
	 * We then retrieve the childs connection information.
	 */
	synchronized(sitter) {
		sitter.start();
		try {
			sitter.wait();
		}
		catch (InterruptedException _) {
		}

		// Create streams from the file descriptors
		stdin_stream = new FileOutputStream(stdin_fd);
		raw_stdout = new FileInputStream(stdout_fd);
		raw_stderr = new FileInputStream(stderr_fd);

		// now signal child to proceed
		FileOutputStream sync = new FileOutputStream(sync_fd);
		byte[] sbuf = new byte[1];
		try {
			sync.write(sbuf);
		}
		catch (IOException _) {
		}
	}
}

native public void destroy();

public int exitValue() {
	if (isalive) {
		throw new IllegalThreadStateException();
	}
	return exit_code;
}

native private int forkAndExec(Object cmd[], Object env[]);
native private int execWait();

public void run() {
}

public InputStream getErrorStream() {
	return raw_stderr;
}

public InputStream getInputStream() {
	return raw_stdout;
}

public OutputStream getOutputStream() {
	return stdin_stream;
}

public int waitFor() throws InterruptedException {
	synchronized(this) {
		while (isalive == true) {
			wait();
		}
	}
	return (exit_code);
}

/**
 * Native callback.
 */
private void processDied(int status) {
	synchronized(this) {
		isalive = false;
		exit_code = status;
		notifyAll();
	}
}

}

@@ -762,16 +762,17 @@
 aders;%09%09
+%09
 // what'
@@ -811,16 +811,98 @@
 ad tidy;
+%09// what's that for?%0A%09Throwable throwable;%09%09// saved to rethrow in correct thread%0A
 %0A%0Apublic
@@ -969,19 +969,39 @@
  arge%5B%5D)
- %7B%0A
+%0A    throws Throwable%0A%7B
 %0A%09stdin_
@@ -1479,36 +1479,232 @@
 %09%09%09i
-f (forkAndExec(_argv, _arge)
+nt fae = 0;%0A%09%09%09try %7B%0A%09%09%09%09fae = forkAndExec(_argv, _arge);%0A%09%09%09%7D%0A%09%09%09catch (Throwable t) %7B%0A%09%09%09%09// save it to rethrow in correct thread%0A%09%09%09%09throwable = t;%0A%09%09%09%09synchronized(this) %7B%0A%09%09%09%09%09notify();%0A%09%09%09%09%7D%0A%09%09%09%09return;%0A%09%09%09%7D%0A%09%09%09if (fae
  == 
@@ -2199,16 +2199,118 @@
 _) %7B%0A%09%09%7D
+%0A%09%09if (throwable != null) %7B%0A%09%09%09// rethrow in current thread%0A%09%09%09throw throwable.fillInStackTrace();%0A%09%09%7D
 %0A%0A%09%09// C

Save throwable in sitter thread to rethrow it in real thread (Debian bug#51230).