[PATCH] [MinGW]: _Jv_close_on_exec

Mohan Embar gnustuff@thisiscool.com
Wed Oct 29 04:04:00 GMT 2003


Hi People,

This attempts to provide an implementation for _Jv_close_on_exec,
which for POSIX is implemented via ::fcntl (fd, F_SETFD, FD_CLOEXEC).
Although no similar notion exists on Win32 (unless I'm missing something),
what you can do is ensure that a handle is non-inheritable by child
processes so that these don't prevent the parent process from closing
the handle. What you then hope for is that the OS will properly release
any as-yet unreleased resources when it exits. It's not perfect, but
it's better than what exists today.

This is implemented via SetHandleInformation(), which is unsupported
on Win9X (it does nothing). I also took the liberty of changing the
signature of _Jv_close_on_exec to take a HANDLE instead of an int
as it does in the POSIX version. In an initial iteration of this
patch, I had made this a HANDLE& and tried to accomodate Win9Xers
by calling DuplicateHandle to create a non-inheritable duplicate
of the incoming handle, closing the original handle, then reassigning
the reference to the duplicated, non-inheritable one. When I
ran my network tests on Win98, this seemed to cause problems, perhaps
because I should have called CloseHandle() instead of closesocket(),
or maybe because of an OS bug. Who knows. Here is my failed attempt:

void
_Jv_platform_close_on_exec (HANDLE& rh)
{
  // Create a non-inheritable copy of this handle
  // and close the original one.
  HANDLE hStdNew;
  if (DuplicateHandle (GetCurrentProcess (), rh,
    GetCurrentProcess (), &hStdNew, 0, 0,
    DUPLICATE_SAME_ACCESS) == 0)
    {
      DWORD dwErrorCode = GetLastError ();
      throw new java::io::IOException (
        _Jv_WinStrError ("Error duplicating handle", dwErrorCode));
    }
  
  // Close the original (presumably inheritable) handle.
  CloseHandle (rh);
  
  // Reassign the reference to the new, non-inheritable handle.
  rh = hStdNew;
}

In any case, the fact that I originally had this as a HANDLE& explains
some of the gymnastics that you see with uses of this in other files.
With the current version (using SetHandleInformation()), my file, networking
and process launching tests run okay on Win98, albeit in the same
slightly incorrect way as before.

-- Mohan
http://www.thisiscool.com/
http://www.animalsong.org/

ChangeLog
2003-10-28  Mohan Embar  <gnustuff@thisiscool.com>

	* include/win32.h (_Jv_platform_close_on_exec): Changed
	signature and declared extern.
	* win32.cc (_Jv_platform_close_on_exec): Implemented.
	* gnu/java/net/natPlainDatagramSocketImplWin32.cc
	(create): Use new signature of _Jv_platform_close_on_exec.
	* gnu/java/net/natPlainSocketImplWin32.cc 
	(create): Eliminated a few typecasts
	Use new signature of _Jv_platform_close_on_exec.
	(accept): Eliminated a few typecasts
	Use new signature of _Jv_platform_close_on_exec.
	* java/io/natFileDescriptorWin32.cc (open): Use
	_Jv_platform_close_on_exec.

Index: include/win32.h
===================================================================
RCS file: /cvs/gcc/gcc/libjava/include/win32.h,v
retrieving revision 1.23
diff -u -2 -r1.23 win32.h
--- include/win32.h	17 Oct 2003 18:44:42 -0000	1.23
+++ include/win32.h	28 Oct 2003 22:08:27 -0000
@@ -98,9 +98,6 @@
 extern int _Jv_pipe (int filedes[2]);
 
-inline void
-_Jv_platform_close_on_exec (jint)
-{
-  // Ignore.
-}
+extern void
+_Jv_platform_close_on_exec (HANDLE h);
 
 #ifdef JV_HASH_SYNCHRONIZATION
Index: win32.cc
===================================================================
RCS file: /cvs/gcc/gcc/libjava/win32.cc,v
retrieving revision 1.17
diff -u -2 -r1.17 win32.cc
--- win32.cc	17 Oct 2003 18:44:40 -0000	1.17
+++ win32.cc	28 Oct 2003 22:08:22 -0000
@@ -350,2 +350,10 @@
   return _pipe (filedes, 4096, _O_BINARY);
 }
+
+void
+_Jv_platform_close_on_exec (HANDLE h)
+{
+  // Mark the handle as non-inheritable. This has
+  // no effect under Win9X.
+  SetHandleInformation (h, HANDLE_FLAG_INHERIT, 0);
+}
Index: gnu/java/net/natPlainDatagramSocketImplWin32.cc
===================================================================
RCS file: /cvs/gcc/gcc/libjava/gnu/java/net/natPlainDatagramSocketImplWin32.cc,v
retrieving revision 1.2
diff -u -2 -r1.2 natPlainDatagramSocketImplWin32.cc
--- gnu/java/net/natPlainDatagramSocketImplWin32.cc	11 Sep 2003 12:30:05 -0000	1.2
+++ gnu/java/net/natPlainDatagramSocketImplWin32.cc	28 Oct 2003 22:08:25 -0000
@@ -70,9 +70,12 @@
     }
 
-  _Jv_platform_close_on_exec (sock);
+  // Cast this to a HANDLE so we can make
+  // it non-inheritable via _Jv_platform_close_on_exec.
+  HANDLE hSocket = (HANDLE) sock;
+  _Jv_platform_close_on_exec (hSocket);
 
   // We use fnum in place of fd here.  From leaving fd null we avoid
   // the double close problem in FileDescriptor.finalize.
-  fnum = (int) sock;
+  fnum = (jint) hSocket;
 }
 
Index: gnu/java/net/natPlainSocketImplWin32.cc
===================================================================
RCS file: /cvs/gcc/gcc/libjava/gnu/java/net/natPlainSocketImplWin32.cc,v
retrieving revision 1.4
diff -u -2 -r1.4 natPlainSocketImplWin32.cc
--- gnu/java/net/natPlainSocketImplWin32.cc	25 Sep 2003 03:04:41 -0000	1.4
+++ gnu/java/net/natPlainSocketImplWin32.cc	28 Oct 2003 22:08:26 -0000
@@ -46,16 +46,19 @@
 gnu::java::net::PlainSocketImpl::create (jboolean stream)
 {
-  int sock = ::socket (AF_INET, stream ? SOCK_STREAM : SOCK_DGRAM, 0);
+  SOCKET sock = ::socket (AF_INET, stream ? SOCK_STREAM : SOCK_DGRAM, 0);
 
-  if (sock == int(INVALID_SOCKET))
+  if (sock == INVALID_SOCKET)
     {
       _Jv_ThrowIOException ();
     }
 
-  _Jv_platform_close_on_exec (sock);
+  // Cast this to a HANDLE so we can make
+  // it non-inheritable via _Jv_platform_close_on_exec.
+  HANDLE hSocket = (HANDLE) sock;
+  _Jv_platform_close_on_exec (hSocket);
 
   // We use fnum in place of fd here.  From leaving fd null we avoid
   // the double close problem in FileDescriptor.finalize.
-  fnum = sock;
+  fnum = (jint) hSocket;
 }
 
@@ -68,5 +71,4 @@
   jbyte *bytes = elements (haddress);
   int len = haddress->length;
-  int i = 1;
 
   if (len == 4)
@@ -235,5 +234,6 @@
   union SockAddr u;
   socklen_t addrlen = sizeof(u);
-  int new_socket = 0;
+  HANDLE hSocket = 0;
+  SOCKET new_socket = 0;
 
   if (timeout > 0)
@@ -250,5 +250,5 @@
         new_socket = ::accept (fnum, (sockaddr*) &u, &addrlen);
 
-        if (new_socket != int(INVALID_SOCKET))
+        if (new_socket != INVALID_SOCKET)
         {
           // This new child socket is nonblocking because the parent
@@ -289,8 +289,11 @@
     }
 
-  if (new_socket == int(INVALID_SOCKET))
+  if (new_socket == INVALID_SOCKET)
     goto error;
 
-  _Jv_platform_close_on_exec (new_socket);
+  // Cast this to a HANDLE so we can make
+  // it non-inheritable via _Jv_platform_close_on_exec.
+  hSocket = (HANDLE) new_socket;
+  _Jv_platform_close_on_exec (hSocket);
 
   jbyteArray raddr;
@@ -313,5 +316,5 @@
     throw new ::java::net::SocketException (JvNewStringUTF ("invalid family"));
 
-  s->fnum = new_socket;
+  s->fnum = (jint) hSocket;
   s->localport = localport;
   s->address = new ::java::net::InetAddress (raddr, NULL);
Index: java/io/natFileDescriptorWin32.cc
===================================================================
RCS file: /cvs/gcc/gcc/libjava/java/io/natFileDescriptorWin32.cc,v
retrieving revision 1.15
diff -u -2 -r1.15 natFileDescriptorWin32.cc
--- java/io/natFileDescriptorWin32.cc	29 Aug 2003 04:21:00 -0000	1.15
+++ java/io/natFileDescriptorWin32.cc	28 Oct 2003 22:08:29 -0000
@@ -134,5 +134,11 @@
       }
     }
-  return (jint)handle;
+    
+  // Make this handle non-inheritable so that child
+  // processes don't inadvertently prevent us from
+  // closing this file.
+  _Jv_platform_close_on_exec (handle);
+
+  return (jint) handle;
 }
 





More information about the Java-patches mailing list