$OpenBSD: patch-jdk_src_solaris_native_java_lang_UNIXProcess_md_c,v 1.2 2009/01/04 23:25:16 kurt Exp $
--- jdk/src/solaris/native/java/lang/UNIXProcess_md.c.orig	Thu Jul 17 03:43:47 2008
+++ jdk/src/solaris/native/java/lang/UNIXProcess_md.c	Sat Aug  2 17:10:19 2008
@@ -40,7 +40,11 @@
 #include <stdlib.h>
 #include <sys/types.h>
 #include <ctype.h>
+#ifdef _ALLBSD_SOURCE
+#include <sys/wait.h>
+#else
 #include <wait.h>
+#endif
 #include <signal.h>
 #include <string.h>
 #include <errno.h>
@@ -49,6 +53,12 @@
 #include <fcntl.h>
 #include <limits.h>
 
+#ifdef __FreeBSD__
+#include <dlfcn.h>
+#include <pthread.h>
+#include <pthread_np.h>
+#endif
+
 #ifndef STDIN_FILENO
 #define STDIN_FILENO 0
 #endif
@@ -259,9 +269,122 @@ Java_java_lang_UNIXProcess_waitForProcessExit(JNIEnv* 
     }
 }
 
+#if defined(__OpenBSD__)
+/*
+ * Directly call _thread_sys_closefrom() so the child process
+ * doesn't reset the parrent's file descriptors to be blocking.
+ * This function is only called from the child process which
+ * is single threaded and about to call execvp() so it is
+ * safe to bypass the threaded closefrom().
+ */
+int _thread_sys_closefrom(int);
+
 static int
 closeDescriptors(void)
 {
+	return _thread_sys_closefrom(FAIL_FILENO + 1);
+}
+
+#elif defined(_ALLBSD_SOURCE)
+
+/*
+ * BSDNOTE: This function was returning 'int' originally.  But it assumed
+ * that OS has some intelegent functionality to close opened-only fds
+ * associated with current process.  Since we have to close them lineary
+ * make it void, until something really new functionality will appear.
+ */
+int closeDescriptors()
+{
+    int max_fd, savei, i, ebadf;
+
+    /*
+     * BSDNOTE: There's no known way to find list of all open file descriptors
+     * associated with process in FreeBSD.  Therefore we have to pass from
+     * fd == 3 to maximum fd per process number.  It's possible to retrive
+     * max number of fd's with three ways: sysctl(kern.maxfilesperproc),
+     * getrlimit(RLIMIT_NOFILE) and getdtablesize().  In current implementation
+     * getdtablesize() returns MIN() of first two ways.
+     *
+     * At my current system maxfileperproc > 7300.  And it's unlikely that
+     * all of these descriptors always are allocated.  Let's use some
+     * "heuristics" to avoid thousands of unneccessary calls.
+     */
+
+#define GUESS_FINISHED	51
+
+    max_fd = getdtablesize();
+    ebadf = 0;
+
+    for (i = 3; i < max_fd; i++) {
+	if (close(i) < 0) { ebadf++; } else { ebadf = 0; }
+	/*
+         * GUESS_FINISHED subsequent calls to close() returned EBADF, assume
+         * we don't have open descriptors anymore
+         */
+	if (ebadf > GUESS_FINISHED) {
+	    return (0);
+        }
+    }
+    return (0);
+}
+
+#if defined(__FreeBSD__)
+
+extern pid_t   __sys_fork(void);
+
+static pid_t
+jdk_fork_wrapper()
+{
+    pid_t resultPid;
+    typedef void (*void_func)();
+    static void_func func_defer = NULL;
+    static void_func func_undefer = NULL;
+    static int is_libc_r = -1;
+
+    if (is_libc_r == -1) {
+
+	/*
+         * BSDNOTE: Check for loaded symbols.
+         *
+         * If "_thread_kern_sig_defer" symbol is found assume we are
+	 * libc_r
+         *
+         * If libc_r is loaded, use fork system call drectly to avoid
+         * problems with using protected pages. 
+         *
+         * --phantom
+	 */
+	func_defer =
+		(void_func)dlsym(RTLD_DEFAULT, "_thread_kern_sig_defer");
+	func_undefer =
+		(void_func)dlsym(RTLD_DEFAULT, "_thread_kern_sig_undefer");
+	if (func_defer != NULL)
+	    is_libc_r = 1;
+	else {
+	    is_libc_r = 0;
+	}
+    }
+
+    if (is_libc_r == 0) {
+	/* Not a libc_r */
+	resultPid = fork();
+    } else {
+        (*func_defer)();		/* call _thread_kern_sig_defer() */
+        resultPid = __sys_fork();
+        if (resultPid != 0)
+ 	    (*func_undefer)();		/* call _thread_kern_sig_undefer() */
+	/* leave child with signals disabled, but reenable in parent */
+    }
+
+    return resultPid;
+}
+#endif /* __FreeBSD__ */
+
+#else /* _ALLBSD_SOURCE */
+
+static int
+closeDescriptors(void)
+{
     DIR *dp;
     struct dirent64 *dirp;
     int from_fd = FAIL_FILENO + 1;
@@ -293,6 +416,7 @@ closeDescriptors(void)
 
     return 1;
 }
+#endif /* !_ALLBSD_SOURCE */
 
 static void
 moveDescriptor(int fd_from, int fd_to)
@@ -510,10 +634,15 @@ readFully(int fd, void *buf, size_t nbyte)
     }
 }
 
+#if defined(__FreeBSD__)
+#undef fork1
+#define fork1() jdk_fork_wrapper()
+#else
 #ifndef __solaris__
 #undef fork1
 #define fork1() fork()
 #endif
+#endif
 
 JNIEXPORT jint JNICALL
 Java_java_lang_UNIXProcess_forkAndExec(JNIEnv *env,
@@ -578,6 +707,28 @@ Java_java_lang_UNIXProcess_forkAndExec(JNIEnv *env,
     if (resultPid == 0) {
         /* Child process */
 
+#ifdef __OpenBSD__
+// XXXBSD: Work-around userland pthread implementation issue.
+// Closing file descriptors will reset them to be blocking.
+// This is problematic for the parent when it attemts to use
+// the blocking fd and deadlocks. Setting them to non-blocking
+// in the child prevents the close/dup2 from resetting them.
+    {
+	int flags;
+	flags = fcntl(STDIN_FILENO, F_GETFL, NULL);
+	if (flags != -1)
+	    fcntl(STDIN_FILENO, F_SETFL, flags | O_NONBLOCK);
+
+	flags = fcntl(STDOUT_FILENO, F_GETFL, NULL);
+	if (flags != -1)
+	    fcntl(STDOUT_FILENO, F_SETFL, flags | O_NONBLOCK);
+
+	flags = fcntl(STDERR_FILENO, F_GETFL, NULL);
+	if (flags != -1)
+	    fcntl(STDOUT_FILENO, F_SETFL, flags | O_NONBLOCK);
+    }
+#endif
+ 
         /* Close the parent sides of the pipes.
            Closing pipe fds here is redundant, since closeDescriptors()
            would do it anyways, but a little paranoia is a good thing. */
