src/java.base/unix/classes/java/io/FileDescriptor.java
changeset 48737 7c12219870fd
parent 48224 be0df5ab3093
--- a/src/java.base/unix/classes/java/io/FileDescriptor.java	Fri Feb 02 10:32:59 2018 -0800
+++ b/src/java.base/unix/classes/java/io/FileDescriptor.java	Fri Feb 02 14:17:07 2018 -0500
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1995, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1995, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -91,6 +91,14 @@
                         fdo.registerCleanup();
                     }
 
+                    public void registerCleanup(FileDescriptor fdo, PhantomCleanable<Object> cleanup) {
+                        fdo.registerCleanup(cleanup);
+                    }
+
+                    public void unregisterCleanup(FileDescriptor fdo) {
+                        fdo.unregisterCleanup();
+                    }
+
                     public void setHandle(FileDescriptor fdo, long handle) {
                         throw new UnsupportedOperationException();
                     }
@@ -105,7 +113,7 @@
     /**
      * Cleanup in case FileDescriptor is not explicitly closed.
      */
-    private FDCleanup cleanup;
+    private PhantomCleanable<Object> cleanup;
 
     /**
      * Constructs an (invalid) FileDescriptor
@@ -206,16 +214,44 @@
     }
 
     /**
-     * Register a cleanup for the current raw fd.
+     * Register a cleanup for the current handle.
      * Used directly in java.io and indirectly via fdAccess.
-     * The cleanup should be registered after the fd is set in the FileDescriptor.
+     * The cleanup should be registered after the handle is set in the FileDescriptor.
      */
     @SuppressWarnings("unchecked")
-    synchronized void registerCleanup() {
+    void registerCleanup() {
+        registerCleanup(null);
+    }
+
+    /**
+     * Register a cleanup for the current handle.
+     * Used directly in java.io and indirectly via fdAccess.
+     * The cleanup should be registered after the handle is set in the FileDescriptor.
+     * @param newCleanable a PhantomCleanable to register
+     */
+    @SuppressWarnings("unchecked")
+    synchronized void registerCleanup(PhantomCleanable<Object> newCleanable) {
         if (cleanup != null) {
             cleanup.clear();
         }
-        cleanup = FDCleanup.create(this);
+        cleanup = (newCleanable == null) ? FDCleanup.create(this) : newCleanable;
+    }
+
+    /**
+     * Unregister a cleanup for the current raw fd.
+     * Used directly in java.io and indirectly via fdAccess.
+     * Normally {@link #close()} should be used except in cases where
+     * it is certain the caller will close the raw fd and the cleanup
+     * must not close the raw fd.  {@link #unregisterCleanup()} must be
+     * called before the raw fd is closed to prevent a race that makes
+     * it possible for the fd to be reallocated to another use and later
+     * the cleanup might be invoked.
+     */
+    synchronized void unregisterCleanup() {
+        if (cleanup != null) {
+            cleanup.clear();
+        }
+        cleanup = null;
     }
 
     /**