8201247: Various cleanups in the attach framework
authorclanger
Wed, 11 Apr 2018 09:47:41 +0200
changeset 49742 1196aa0be8be
parent 49741 0d8ed8b2ac4f
child 49743 b2da6c360225
8201247: Various cleanups in the attach framework Reviewed-by: goetz, cjplummer
src/hotspot/os/aix/attachListener_aix.cpp
src/hotspot/os/aix/globals_aix.hpp
src/hotspot/os/bsd/attachListener_bsd.cpp
src/hotspot/os/linux/attachListener_linux.cpp
src/hotspot/os/solaris/attachListener_solaris.cpp
src/hotspot/os/windows/attachListener_windows.cpp
src/jdk.attach/aix/classes/sun/tools/attach/VirtualMachineImpl.java
src/jdk.attach/aix/native/libattach/VirtualMachineImpl.c
src/jdk.attach/linux/classes/sun/tools/attach/VirtualMachineImpl.java
src/jdk.attach/linux/native/libattach/VirtualMachineImpl.c
src/jdk.attach/macosx/classes/sun/tools/attach/VirtualMachineImpl.java
src/jdk.attach/macosx/native/libattach/VirtualMachineImpl.c
src/jdk.attach/solaris/classes/sun/tools/attach/VirtualMachineImpl.java
src/jdk.attach/solaris/native/libattach/VirtualMachineImpl.c
src/jdk.attach/windows/native/libattach/VirtualMachineImpl.c
--- a/src/hotspot/os/aix/attachListener_aix.cpp	Wed Apr 11 08:18:13 2018 +0200
+++ b/src/hotspot/os/aix/attachListener_aix.cpp	Wed Apr 11 09:47:41 2018 +0200
@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2012, 2016 SAP SE. All rights reserved.
+ * Copyright (c) 2012, 2018 SAP SE. 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
@@ -30,12 +30,12 @@
 #include "services/attachListener.hpp"
 #include "services/dtraceAttacher.hpp"
 
-#include <unistd.h>
 #include <signal.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
 #include <sys/types.h>
-#include <sys/socket.h>
 #include <sys/un.h>
-#include <sys/stat.h>
+#include <unistd.h>
 
 #ifndef UNIX_PATH_MAX
 #define UNIX_PATH_MAX   sizeof(((struct sockaddr_un *)0)->sun_path)
@@ -145,10 +145,10 @@
   }
   char* next() {
     if (*_pos == '\0') {
+      // advance the iterator if possible (null arguments)
       if (_pos < _end) {
         _pos += 1;
       }
-
       return NULL;
     }
     char* res = _pos;
@@ -233,10 +233,10 @@
   // put in listen mode, set permissions, and rename into place
   res = ::listen(listener, 5);
   if (res == 0) {
-      RESTARTABLE(::chmod(initial_path, (S_IREAD|S_IWRITE) & ~(S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH)), res);
-      if (res == 0) {
-          res = ::rename(initial_path, path);
-      }
+    RESTARTABLE(::chmod(initial_path, S_IREAD|S_IWRITE), res);
+    if (res == 0) {
+      res = ::rename(initial_path, path);
+    }
   }
   if (res == -1) {
     ::close(listener);
@@ -284,10 +284,12 @@
     // Don't block on interrupts because this will
     // hang in the clean-up when shutting down.
     n = read(s, buf+off, left);
+    assert(n <= left, "buffer was too small, impossible!");
+    buf[max_len - 1] = '\0';
     if (n == -1) {
       return NULL;      // reset by peer or other error
     }
-    if (n == 0) {       // end of file reached
+    if (n == 0) {
       break;
     }
     for (int i=0; i<n; i++) {
@@ -362,7 +364,7 @@
     socklen_t len = sizeof(addr);
     memset(&addr, 0, len);
     // We must prevent accept blocking on the socket if it has been shut down.
-    // Therefore we allow interrups and check whether we have been shut down already.
+    // Therefore we allow interrupts and check whether we have been shut down already.
     if (AixAttachListener::is_shutdown()) {
       return NULL;
     }
@@ -371,19 +373,11 @@
       return NULL;      // log a warning?
     }
 
-    // Added timeouts for read and write.  If we get no request within the
-    // next AttachListenerTimeout milliseconds we just finish the connection.
-    struct timeval tv;
-    tv.tv_sec = 0;
-    tv.tv_usec = AttachListenerTimeout * 1000;
-    ::setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, (char*)&tv, sizeof(tv));
-    ::setsockopt(s, SOL_SOCKET, SO_SNDTIMEO, (char*)&tv, sizeof(tv));
-
     // get the credentials of the peer and check the effective uid/guid
-    // - check with jeff on this.
     struct peercred_struct cred_info;
     socklen_t optlen = sizeof(cred_info);
     if (::getsockopt(s, SOL_SOCKET, SO_PEERID, (void*)&cred_info, &optlen) == -1) {
+      log_debug(attach)("Failed to get socket option SO_PEERID");
       ::close(s);
       continue;
     }
@@ -391,6 +385,7 @@
     gid_t egid = getegid();
 
     if (cred_info.euid != euid || cred_info.egid != egid) {
+      log_debug(attach)("euid/egid check failed (%d/%d vs %d/%d)", cred_info.euid, cred_info.egid, euid, egid);
       ::close(s);
       continue;
     }
@@ -532,10 +527,10 @@
   if (init_at_startup() || is_initialized()) {
     return false;               // initialized at startup or already initialized
   }
-  char fn[PATH_MAX+1];
-  sprintf(fn, ".attach_pid%d", os::current_process_id());
+  char fn[PATH_MAX + 1];
   int ret;
   struct stat64 st;
+  sprintf(fn, ".attach_pid%d", os::current_process_id());
   RESTARTABLE(::stat64(fn, &st), ret);
   if (ret == -1) {
     log_trace(attach)("Failed to find attach file: %s, trying alternate", fn);
@@ -551,7 +546,7 @@
     // a bogus user creates the file
     if (st.st_uid == geteuid()) {
       init();
-      log_trace(attach)("Attach trigerred by %s", fn);
+      log_trace(attach)("Attach triggered by %s", fn);
       return true;
     } else {
       log_debug(attach)("File %s has wrong user id %d (vs %d). Attach is not triggered", fn, st.st_uid, geteuid());
--- a/src/hotspot/os/aix/globals_aix.hpp	Wed Apr 11 08:18:13 2018 +0200
+++ b/src/hotspot/os/aix/globals_aix.hpp	Wed Apr 11 09:47:41 2018 +0200
@@ -1,6 +1,6 @@
 /*
- * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2012, 2015 SAP SE. All rights reserved.
+ * Copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2018 SAP SE. 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
@@ -51,10 +51,6 @@
   product(bool, AllowExtshm, false,                                                 \
           "Allow VM to run with EXTSHM=ON.")                                        \
                                                                                     \
-  product(intx, AttachListenerTimeout, 1000,                                        \
-          "Timeout in ms the attach listener waits for a request")                  \
-          range(0, 2147483)                                                         \
-                                                                                    \
   /*  Maximum expected size of the data segment. That correlates with the      */   \
   /*  to the maximum C Heap consumption we expect.                             */   \
   /*  We need to know this because we need to leave "breathing space" for the  */   \
--- a/src/hotspot/os/bsd/attachListener_bsd.cpp	Wed Apr 11 08:18:13 2018 +0200
+++ b/src/hotspot/os/bsd/attachListener_bsd.cpp	Wed Apr 11 09:47:41 2018 +0200
@@ -137,6 +137,10 @@
   }
   char* next() {
     if (*_pos == '\0') {
+      // advance the iterator if possible (null arguments)
+      if (_pos < _end) {
+        _pos += 1;
+      }
       return NULL;
     }
     char* res = _pos;
@@ -195,6 +199,7 @@
 
   // bind socket
   struct sockaddr_un addr;
+  memset((void *)&addr, 0, sizeof(addr));
   addr.sun_family = AF_UNIX;
   strcpy(addr.sun_path, initial_path);
   ::unlink(initial_path);
@@ -260,6 +265,8 @@
   do {
     int n;
     RESTARTABLE(read(s, buf+off, left), n);
+    assert(n <= left, "buffer was too small, impossible!");
+    buf[max_len - 1] = '\0';
     if (n == -1) {
       return NULL;      // reset by peer or other error
     }
@@ -342,10 +349,10 @@
     }
 
     // get the credentials of the peer and check the effective uid/guid
-    // - check with jeff on this.
     uid_t puid;
     gid_t pgid;
     if (::getpeereid(s, &puid, &pgid) != 0) {
+      log_debug(attach)("Failed to get peer id");
       ::close(s);
       continue;
     }
@@ -353,6 +360,7 @@
     gid_t egid = getegid();
 
     if (puid != euid || pgid != egid) {
+      log_debug(attach)("euid/egid check failed (%d/%d vs %d/%d)", puid, pgid, euid, egid);
       ::close(s);
       continue;
     }
@@ -438,7 +446,6 @@
   return op;
 }
 
-
 // Performs initialization at vm startup
 // For BSD we remove any stale .java_pid file which could cause
 // an attaching process to think we are ready to receive on the
@@ -497,7 +504,6 @@
   char fn[PATH_MAX + 1];
   int ret;
   struct stat st;
-
   snprintf(fn, PATH_MAX + 1, "%s/.attach_pid%d",
            os::get_temp_directory(), os::current_process_id());
   RESTARTABLE(::stat(fn, &st), ret);
@@ -509,7 +515,7 @@
     // a bogus user creates the file
     if (st.st_uid == geteuid()) {
       init();
-      log_trace(attach)("Attach trigerred by %s", fn);
+      log_trace(attach)("Attach triggered by %s", fn);
       return true;
     } else {
       log_debug(attach)("File %s has wrong user id %d (vs %d). Attach is not triggered", fn, st.st_uid, geteuid());
--- a/src/hotspot/os/linux/attachListener_linux.cpp	Wed Apr 11 08:18:13 2018 +0200
+++ b/src/hotspot/os/linux/attachListener_linux.cpp	Wed Apr 11 09:47:41 2018 +0200
@@ -138,6 +138,10 @@
   }
   char* next() {
     if (*_pos == '\0') {
+      // advance the iterator if possible (null arguments)
+      if (_pos < _end) {
+        _pos += 1;
+      }
       return NULL;
     }
     char* res = _pos;
@@ -196,6 +200,7 @@
 
   // bind socket
   struct sockaddr_un addr;
+  memset((void *)&addr, 0, sizeof(addr));
   addr.sun_family = AF_UNIX;
   strcpy(addr.sun_path, initial_path);
   ::unlink(initial_path);
@@ -208,10 +213,10 @@
   // put in listen mode, set permissions, and rename into place
   res = ::listen(listener, 5);
   if (res == 0) {
-      RESTARTABLE(::chmod(initial_path, S_IREAD|S_IWRITE), res);
-      if (res == 0) {
-          res = ::rename(initial_path, path);
-      }
+    RESTARTABLE(::chmod(initial_path, S_IREAD|S_IWRITE), res);
+    if (res == 0) {
+      res = ::rename(initial_path, path);
+    }
   }
   if (res == -1) {
     ::close(listener);
@@ -340,10 +345,10 @@
     }
 
     // get the credentials of the peer and check the effective uid/guid
-    // - check with jeff on this.
     struct ucred cred_info;
     socklen_t optlen = sizeof(cred_info);
     if (::getsockopt(s, SOL_SOCKET, SO_PEERCRED, (void*)&cred_info, &optlen) == -1) {
+      log_debug(attach)("Failed to get socket option SO_PEERCRED");
       ::close(s);
       continue;
     }
@@ -351,6 +356,7 @@
     gid_t egid = getegid();
 
     if (cred_info.uid != euid || cred_info.gid != egid) {
+      log_debug(attach)("euid/egid check failed (%d/%d vs %d/%d)", cred_info.uid, cred_info.gid, euid, egid);
       ::close(s);
       continue;
     }
@@ -436,7 +442,6 @@
   return op;
 }
 
-
 // Performs initialization at vm startup
 // For Linux we remove any stale .java_pid file which could cause
 // an attaching process to think we are ready to receive on the
@@ -492,10 +497,10 @@
   if (init_at_startup() || is_initialized()) {
     return false;               // initialized at startup or already initialized
   }
-  char fn[PATH_MAX+1];
-  sprintf(fn, ".attach_pid%d", os::current_process_id());
+  char fn[PATH_MAX + 1];
   int ret;
   struct stat64 st;
+  sprintf(fn, ".attach_pid%d", os::current_process_id());
   RESTARTABLE(::stat64(fn, &st), ret);
   if (ret == -1) {
     log_trace(attach)("Failed to find attach file: %s, trying alternate", fn);
@@ -511,10 +516,10 @@
     // a bogus user creates the file
     if (st.st_uid == geteuid()) {
       init();
-      log_trace(attach)("Attach trigerred by %s", fn);
+      log_trace(attach)("Attach triggered by %s", fn);
       return true;
     } else {
-      log_debug(attach)("File %s has wrong user id %d (vs %d). Attach is not trigerred", fn, st.st_uid, geteuid());
+      log_debug(attach)("File %s has wrong user id %d (vs %d). Attach is not triggered", fn, st.st_uid, geteuid());
     }
   }
   return false;
--- a/src/hotspot/os/solaris/attachListener_solaris.cpp	Wed Apr 11 08:18:13 2018 +0200
+++ b/src/hotspot/os/solaris/attachListener_solaris.cpp	Wed Apr 11 09:47:41 2018 +0200
@@ -186,6 +186,10 @@
   }
   char* next() {
     if (*_pos == '\0') {
+      // advance the iterator if possible (null arguments)
+      if (_pos < _end) {
+        _pos += 1;
+      }
       return NULL;
     }
     char* res = _pos;
@@ -644,10 +648,10 @@
   if (init_at_startup() || is_initialized()) {
     return false;               // initialized at startup or already initialized
   }
-  char fn[PATH_MAX+1];
-  sprintf(fn, ".attach_pid%d", os::current_process_id());
+  char fn[PATH_MAX + 1];
   int ret;
   struct stat64 st;
+  sprintf(fn, ".attach_pid%d", os::current_process_id());
   RESTARTABLE(::stat64(fn, &st), ret);
   if (ret == -1) {
     log_trace(attach)("Failed to find attach file: %s, trying alternate", fn);
@@ -663,7 +667,10 @@
     // a bogus user creates the file
     if (st.st_uid == geteuid()) {
       init();
+      log_trace(attach)("Attach triggered by %s", fn);
       return true;
+    } else {
+      log_debug(attach)("File %s has wrong user id %d (vs %d). Attach is not triggered", fn, st.st_uid, geteuid());
     }
   }
   return false;
--- a/src/hotspot/os/windows/attachListener_windows.cpp	Wed Apr 11 08:18:13 2018 +0200
+++ b/src/hotspot/os/windows/attachListener_windows.cpp	Wed Apr 11 09:47:41 2018 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 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
@@ -131,12 +131,12 @@
     pipe_name_max = 256             // maximum pipe name
   };
 
-  char _pipe[pipe_name_max+1];
+  char _pipe[pipe_name_max + 1];
 
   const char* pipe() const                              { return _pipe; }
   void set_pipe(const char* pipe) {
-    assert(strlen(pipe) <= pipe_name_max, "execeds maximum length of pipe name");
-    strcpy(_pipe, pipe);
+    assert(strlen(pipe) <= pipe_name_max, "exceeds maximum length of pipe name");
+    os::snprintf(_pipe, sizeof(_pipe), "%s", pipe);
   }
 
   HANDLE open_pipe();
@@ -329,12 +329,20 @@
 
     fSuccess = write_pipe(hPipe, msg, (int)strlen(msg));
     if (fSuccess) {
-      write_pipe(hPipe, (char*) result_stream->base(), (int)(result_stream->size()));
+      fSuccess = write_pipe(hPipe, (char*)result_stream->base(), (int)(result_stream->size()));
     }
 
     // Need to flush buffers
     FlushFileBuffers(hPipe);
     CloseHandle(hPipe);
+
+    if (fSuccess) {
+      log_debug(attach)("wrote result of attach operation %s to pipe %s", name(), pipe());
+    } else {
+      log_error(attach)("failure writing result of operation %s to pipe %s", name(), pipe());
+    }
+  } else {
+    log_error(attach)("could not open pipe %s to send result of operation %s", pipe(), name());
   }
 
   DWORD res = ::WaitForSingleObject(Win32AttachListener::mutex(), INFINITE);
--- a/src/jdk.attach/aix/classes/sun/tools/attach/VirtualMachineImpl.java	Wed Apr 11 08:18:13 2018 +0200
+++ b/src/jdk.attach/aix/classes/sun/tools/attach/VirtualMachineImpl.java	Wed Apr 11 09:47:41 2018 +0200
@@ -1,6 +1,6 @@
 /*
- * Copyright (c) 2008, 2017, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2015 SAP SE. All rights reserved.
+ * Copyright (c) 2008, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2018, SAP SE. 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
@@ -34,8 +34,6 @@
 import java.io.IOException;
 import java.io.File;
 
-// Based on linux/classes/sun/tools/attach/VirtualMachineImpl.java.
-
 /*
  * Aix implementation of HotSpotVirtualMachine
  */
@@ -140,7 +138,7 @@
      * Execute the given command in the target VM.
      */
     InputStream execute(String cmd, Object ... args) throws AgentLoadException, IOException {
-        assert args.length <= 3;            // includes null
+        assert args.length <= 3;                // includes null
 
         // did we detach?
         synchronized (this) {
@@ -261,7 +259,7 @@
         }
     }
 
-    // On Solaris/Linux/Aix a simple handshake is used to start the attach mechanism
+    // On Aix a simple handshake is used to start the attach mechanism
     // if not already started. The client creates a .attach_pid<pid> file in the
     // target VM's working directory (or temp directory), and the SIGQUIT handler
     // checks for the file.
--- a/src/jdk.attach/aix/native/libattach/VirtualMachineImpl.c	Wed Apr 11 08:18:13 2018 +0200
+++ b/src/jdk.attach/aix/native/libattach/VirtualMachineImpl.c	Wed Apr 11 09:47:41 2018 +0200
@@ -1,6 +1,6 @@
 /*
- * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2015 SAP SE. All rights reserved.
+ * Copyright (c) 2008, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2018, SAP SE. 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
@@ -24,27 +24,18 @@
  * questions.
  */
 
-#include "jni.h"
 #include "jni_util.h"
-#include "jvm.h"
 
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/un.h>
+#include <errno.h>
+#include <signal.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
-#include <errno.h>
 #include <unistd.h>
-#include <signal.h>
-#include <dirent.h>
-#include <ctype.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <sys/stat.h>
-#include <sys/un.h>
-
-/*
- * Based on 'LinuxVirtualMachine.c'. Non-relevant code has been removed and all
- * occurrences of the string "Linux" have been replaced by "Aix".
- */
 
 #include "sun_tools_attach_VirtualMachineImpl.h"
 
@@ -67,15 +58,6 @@
     if (fd == -1) {
         JNU_ThrowIOExceptionWithLastError(env, "socket");
     }
-    /* added time out values */
-    else {
-        struct timeval tv;
-        tv.tv_sec = 2 * 60;
-        tv.tv_usec = 0;
-
-        setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, (char*)&tv, sizeof(tv));
-        setsockopt(fd, SOL_SOCKET, SO_SNDTIMEO, (char*)&tv, sizeof(tv));
-    }
     return (jint)fd;
 }
 
@@ -125,23 +107,6 @@
     }
 }
 
-
-/*
- * Structure and callback function used to send a QUIT signal to all
- * children of a given process
- */
-typedef struct {
-    pid_t ppid;
-} SendQuitContext;
-
-static void SendQuitCallback(const pid_t pid, void* user_data) {
-    SendQuitContext* context = (SendQuitContext*)user_data;
-    pid_t parent = getParent(pid);
-    if (parent == context->ppid) {
-        kill(pid, SIGQUIT);
-    }
-}
-
 /*
  * Class:     sun_tools_attach_VirtualMachineImpl
  * Method:    sendQuitTo
@@ -169,7 +134,7 @@
         struct stat64 sb;
         uid_t uid, gid;
         int res;
-        /* added missing initialization of the stat64 buffer */
+
         memset(&sb, 0, sizeof(struct stat64));
 
         /*
@@ -189,21 +154,21 @@
             char msg[100];
             jboolean isError = JNI_FALSE;
             if (sb.st_uid != uid) {
-                jio_snprintf(msg, sizeof(msg)-1,
+                snprintf(msg, sizeof(msg),
                     "file should be owned by the current user (which is %d) but is owned by %d", uid, sb.st_uid);
                 isError = JNI_TRUE;
             } else if (sb.st_gid != gid) {
-                jio_snprintf(msg, sizeof(msg)-1,
+                snprintf(msg, sizeof(msg),
                     "file's group should be the current group (which is %d) but the group is %d", gid, sb.st_gid);
                 isError = JNI_TRUE;
             } else if ((sb.st_mode & (S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH)) != 0) {
-                jio_snprintf(msg, sizeof(msg)-1,
+                snprintf(msg, sizeof(msg),
                     "file should only be readable and writable by the owner but has 0%03o access", sb.st_mode & 0777);
                 isError = JNI_TRUE;
             }
             if (isError) {
                 char buf[256];
-                jio_snprintf(buf, sizeof(buf)-1, "well-known file %s is not secure: %s", p, msg);
+                snprintf(buf, sizeof(buf), "well-known file %s is not secure: %s", p, msg);
                 JNU_ThrowIOException(env, buf);
             }
         } else {
@@ -229,11 +194,7 @@
   (JNIEnv *env, jclass cls, jint fd)
 {
     int res;
-    /* Fixed deadlock when this call of close by the client is not seen by the attach server
-     * which has accepted the (very short) connection already and is waiting for the request. But read don't get a byte,
-     * because the close is lost without shutdown.
-     */
-    shutdown(fd, 2);
+    shutdown(fd, SHUT_RDWR);
     RESTARTABLE(close(fd), res);
 }
 
--- a/src/jdk.attach/linux/classes/sun/tools/attach/VirtualMachineImpl.java	Wed Apr 11 08:18:13 2018 +0200
+++ b/src/jdk.attach/linux/classes/sun/tools/attach/VirtualMachineImpl.java	Wed Apr 11 09:47:41 2018 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 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
@@ -105,7 +105,7 @@
             } finally {
                 f.delete();
             }
-      }
+        }
 
         // Check that the file owner/permission to avoid attaching to
         // bogus process
@@ -274,7 +274,7 @@
         return new File(root, ".java_pid" + ns_pid);
     }
 
-    // On Solaris/Linux a simple handshake is used to start the attach mechanism
+    // On Linux a simple handshake is used to start the attach mechanism
     // if not already started. The client creates a .attach_pid<pid> file in the
     // target VM's working directory (or temp directory), and the SIGQUIT handler
     // checks for the file.
@@ -356,8 +356,6 @@
 
     //-- native methods
 
-    static native void sendQuitToChildrenOf(int pid) throws IOException;
-
     static native void sendQuitTo(int pid) throws IOException;
 
     static native void checkPermissions(String path) throws IOException;
--- a/src/jdk.attach/linux/native/libattach/VirtualMachineImpl.c	Wed Apr 11 08:18:13 2018 +0200
+++ b/src/jdk.attach/linux/native/libattach/VirtualMachineImpl.c	Wed Apr 11 09:47:41 2018 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 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
@@ -23,23 +23,18 @@
  * questions.
  */
 
-#include "jni.h"
 #include "jni_util.h"
-#include "jvm.h"
 
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/un.h>
+#include <errno.h>
+#include <signal.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
-#include <errno.h>
 #include <unistd.h>
-#include <signal.h>
-#include <dirent.h>
-#include <ctype.h>
-#include <sys/types.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <sys/stat.h>
-#include <sys/un.h>
 
 #include "sun_tools_attach_VirtualMachineImpl.h"
 
@@ -55,85 +50,6 @@
 DEF_STATIC_JNI_OnLoad
 
 /*
- * Defines a callback that is invoked for each process
- */
-typedef void (*ProcessCallback)(const pid_t pid, void* user_data);
-
-/*
- * Invokes the callback function for each process
- */
-static void forEachProcess(ProcessCallback f, void* user_data) {
-    DIR* dir;
-    struct dirent* ptr;
-
-    /*
-     * To locate the children we scan /proc looking for files that have a
-     * position integer as a filename.
-     */
-    if ((dir = opendir("/proc")) == NULL) {
-        return;
-    }
-    while ((ptr = readdir(dir)) != NULL) {
-        pid_t pid;
-
-        /* skip current/parent directories */
-        if (strcmp(ptr->d_name, ".") == 0 || strcmp(ptr->d_name, "..") == 0) {
-            continue;
-        }
-
-        /* skip files that aren't numbers */
-        pid = (pid_t)atoi(ptr->d_name);
-        if ((int)pid <= 0) {
-            continue;
-        }
-
-        /* invoke the callback */
-        (*f)(pid, user_data);
-    }
-    closedir(dir);
-}
-
-
-/*
- * Returns the parent pid of a given pid, or -1 if not found
- */
-static pid_t getParent(pid_t pid) {
-    char state;
-    FILE* fp;
-    char stat[2048];
-    int statlen;
-    char fn[32];
-    int i, p;
-    char* s;
-
-    /*
-     * try to open /proc/%d/stat
-     */
-    sprintf(fn, "/proc/%d/stat", pid);
-    fp = fopen(fn, "r");
-    if (fp == NULL) {
-        return -1;
-    }
-
-    /*
-     * The format is: pid (command) state ppid ...
-     * As the command could be anything we must find the right most
-     * ")" and then skip the white spaces that follow it.
-     */
-    statlen = fread(stat, 1, 2047, fp);
-    stat[statlen] = '\0';
-    fclose(fp);
-    s = strrchr(stat, ')');
-    if (s == NULL) {
-        return -1;
-    }
-    do s++; while (isspace(*s));
-    i = sscanf(s, "%c %d", &state, &p);
-    return (pid_t)p;
-}
-
-
-/*
  * Class:     sun_tools_attach_VirtualMachineImpl
  * Method:    socket
  * Signature: ()I
@@ -195,39 +111,6 @@
 }
 
 /*
- * Structure and callback function used to send a QUIT signal to all
- * children of a given process
- */
-typedef struct {
-    pid_t ppid;
-} SendQuitContext;
-
-static void SendQuitCallback(const pid_t pid, void* user_data) {
-    SendQuitContext* context = (SendQuitContext*)user_data;
-    pid_t parent = getParent(pid);
-    if (parent == context->ppid) {
-        kill(pid, SIGQUIT);
-    }
-}
-
-/*
- * Class:     sun_tools_attach_VirtualMachineImpl
- * Method:    sendQuitToChildrenOf
- * Signature: (I)V
- */
-JNIEXPORT void JNICALL Java_sun_tools_attach_VirtualMachineImpl_sendQuitToChildrenOf
-  (JNIEnv *env, jclass cls, jint pid)
-{
-    SendQuitContext context;
-    context.ppid = (pid_t)pid;
-
-    /*
-     * Iterate over all children of 'pid' and send a QUIT signal to each.
-     */
-    forEachProcess(SendQuitCallback, (void*)&context);
-}
-
-/*
  * Class:     sun_tools_attach_VirtualMachineImpl
  * Method:    sendQuitTo
  * Signature: (I)V
@@ -255,6 +138,8 @@
         uid_t uid, gid;
         int res;
 
+        memset(&sb, 0, sizeof(struct stat64));
+
         /*
          * Check that the path is owned by the effective uid/gid of this
          * process. Also check that group/other access is not allowed.
@@ -272,21 +157,21 @@
             char msg[100];
             jboolean isError = JNI_FALSE;
             if (sb.st_uid != uid) {
-                jio_snprintf(msg, sizeof(msg)-1,
+                snprintf(msg, sizeof(msg),
                     "file should be owned by the current user (which is %d) but is owned by %d", uid, sb.st_uid);
                 isError = JNI_TRUE;
             } else if (sb.st_gid != gid) {
-                jio_snprintf(msg, sizeof(msg)-1,
+                snprintf(msg, sizeof(msg),
                     "file's group should be the current group (which is %d) but the group is %d", gid, sb.st_gid);
                 isError = JNI_TRUE;
             } else if ((sb.st_mode & (S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH)) != 0) {
-                jio_snprintf(msg, sizeof(msg)-1,
+                snprintf(msg, sizeof(msg),
                     "file should only be readable and writable by the owner but has 0%03o access", sb.st_mode & 0777);
                 isError = JNI_TRUE;
             }
             if (isError) {
                 char buf[256];
-                jio_snprintf(buf, sizeof(buf)-1, "well-known file %s is not secure: %s", p, msg);
+                snprintf(buf, sizeof(buf), "well-known file %s is not secure: %s", p, msg);
                 JNU_ThrowIOException(env, buf);
             }
         } else {
@@ -312,6 +197,7 @@
   (JNIEnv *env, jclass cls, jint fd)
 {
     int res;
+    shutdown(fd, SHUT_RDWR);
     RESTARTABLE(close(fd), res);
 }
 
@@ -366,8 +252,8 @@
 
         RESTARTABLE(write(fd, buf, len), n);
         if (n > 0) {
-           off += n;
-           remaining -= n;
+            off += n;
+            remaining -= n;
         } else {
             JNU_ThrowIOExceptionWithLastError(env, "write");
             return;
--- a/src/jdk.attach/macosx/classes/sun/tools/attach/VirtualMachineImpl.java	Wed Apr 11 08:18:13 2018 +0200
+++ b/src/jdk.attach/macosx/classes/sun/tools/attach/VirtualMachineImpl.java	Wed Apr 11 09:47:41 2018 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 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
@@ -281,8 +281,7 @@
     }
 
     private File createAttachFile(int pid) throws IOException {
-        String fn = ".attach_pid" + pid;
-        File f = new File(tmpdir, fn);
+        File f = new File(tmpdir, ".attach_pid" + pid);
         createAttachFile0(f.getPath());
         return f;
     }
--- a/src/jdk.attach/macosx/native/libattach/VirtualMachineImpl.c	Wed Apr 11 08:18:13 2018 +0200
+++ b/src/jdk.attach/macosx/native/libattach/VirtualMachineImpl.c	Wed Apr 11 09:47:41 2018 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 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
@@ -23,24 +23,20 @@
  * questions.
  */
 
-#include "jni.h"
 #include "jni_util.h"
-#include "jvm.h"
 
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <sys/syslimits.h>
+#include <sys/types.h>
+#include <sys/un.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <signal.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
-#include <errno.h>
 #include <unistd.h>
-#include <signal.h>
-#include <dirent.h>
-#include <ctype.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <sys/stat.h>
-#include <sys/syslimits.h>
-#include <sys/un.h>
-#include <fcntl.h>
 
 #include "sun_tools_attach_VirtualMachineImpl.h"
 
@@ -144,6 +140,8 @@
         uid_t uid, gid;
         int res;
 
+        memset(&sb, 0, sizeof(struct stat));
+
         /*
          * Check that the path is owned by the effective uid/gid of this
          * process. Also check that group/other access is not allowed.
@@ -161,21 +159,21 @@
             char msg[100];
             jboolean isError = JNI_FALSE;
             if (sb.st_uid != uid) {
-                jio_snprintf(msg, sizeof(msg)-1,
+                snprintf(msg, sizeof(msg),
                     "file should be owned by the current user (which is %d) but is owned by %d", uid, sb.st_uid);
                 isError = JNI_TRUE;
             } else if (sb.st_gid != gid) {
-                jio_snprintf(msg, sizeof(msg)-1,
+                snprintf(msg, sizeof(msg),
                     "file's group should be the current group (which is %d) but the group is %d", gid, sb.st_gid);
                 isError = JNI_TRUE;
             } else if ((sb.st_mode & (S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH)) != 0) {
-                jio_snprintf(msg, sizeof(msg)-1,
+                snprintf(msg, sizeof(msg),
                     "file should only be readable and writable by the owner but has 0%03o access", sb.st_mode & 0777);
                 isError = JNI_TRUE;
             }
             if (isError) {
                 char buf[256];
-                jio_snprintf(buf, sizeof(buf)-1, "well-known file %s is not secure: %s", p, msg);
+                snprintf(buf, sizeof(buf), "well-known file %s is not secure: %s", p, msg);
                 JNU_ThrowIOException(env, buf);
             }
         } else {
@@ -201,6 +199,7 @@
   (JNIEnv *env, jclass cls, jint fd)
 {
     int res;
+    shutdown(fd, SHUT_RDWR);
     RESTARTABLE(close(fd), res);
 }
 
@@ -255,8 +254,8 @@
 
         RESTARTABLE(write(fd, buf, len), n);
         if (n > 0) {
-           off += n;
-           remaining -= n;
+            off += n;
+            remaining -= n;
         } else {
             JNU_ThrowIOExceptionWithLastError(env, "write");
             return;
--- a/src/jdk.attach/solaris/classes/sun/tools/attach/VirtualMachineImpl.java	Wed Apr 11 08:18:13 2018 +0200
+++ b/src/jdk.attach/solaris/classes/sun/tools/attach/VirtualMachineImpl.java	Wed Apr 11 09:47:41 2018 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 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
@@ -225,7 +225,7 @@
         return fd;
     }
 
-    // On Solaris/Linux a simple handshake is used to start the attach mechanism
+    // On Solaris a simple handshake is used to start the attach mechanism
     // if not already started. The client creates a .attach_pid<pid> file in the
     // target VM's working directory (or temporary directory), and the SIGQUIT
     // handler checks for the file.
--- a/src/jdk.attach/solaris/native/libattach/VirtualMachineImpl.c	Wed Apr 11 08:18:13 2018 +0200
+++ b/src/jdk.attach/solaris/native/libattach/VirtualMachineImpl.c	Wed Apr 11 09:47:41 2018 +0200
@@ -22,20 +22,19 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
+
+#include "jni_util.h"
+
+#include <sys/stat.h>
 #include <sys/types.h>
-#include <sys/stat.h>
 #include <door.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <signal.h>
 #include <stdlib.h>
-#include <unistd.h>
-#include <signal.h>
 #include <string.h>
-#include <fcntl.h>
-#include <errno.h>
-#include <limits.h>
-
-#include "jni.h"
-#include "jni_util.h"
-#include "jvm.h"
+#include <unistd.h>
 
 #include "sun_tools_attach_VirtualMachineImpl.h"
 
@@ -105,6 +104,8 @@
         uid_t uid, gid;
         int res;
 
+        memset(&sb, 0, sizeof(struct stat64));
+
         /*
          * Check that the path is owned by the effective uid/gid of this
          * process. Also check that group/other access is not allowed.
@@ -122,21 +123,21 @@
             char msg[100];
             jboolean isError = JNI_FALSE;
             if (sb.st_uid != uid) {
-                jio_snprintf(msg, sizeof(msg)-1,
+                snprintf(msg, sizeof(msg),
                     "file should be owned by the current user (which is %d) but is owned by %d", uid, sb.st_uid);
                 isError = JNI_TRUE;
             } else if (sb.st_gid != gid) {
-                jio_snprintf(msg, sizeof(msg)-1,
+                snprintf(msg, sizeof(msg),
                     "file's group should be the current group (which is %d) but the group is %d", gid, sb.st_gid);
                 isError = JNI_TRUE;
             } else if ((sb.st_mode & (S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH)) != 0) {
-                jio_snprintf(msg, sizeof(msg)-1,
+                snprintf(msg, sizeof(msg),
                     "file should only be readable and writable by the owner but has 0%03o access", sb.st_mode & 0777);
                 isError = JNI_TRUE;
             }
             if (isError) {
                 char buf[256];
-                jio_snprintf(buf, sizeof(buf)-1, "well-known file %s is not secure: %s", p, msg);
+                snprintf(buf, sizeof(buf), "well-known file %s is not secure: %s", p, msg);
                 JNU_ThrowIOException(env, buf);
             }
         } else {
--- a/src/jdk.attach/windows/native/libattach/VirtualMachineImpl.c	Wed Apr 11 08:18:13 2018 +0200
+++ b/src/jdk.attach/windows/native/libattach/VirtualMachineImpl.c	Wed Apr 11 09:47:41 2018 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 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
@@ -22,16 +22,15 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
+
+#include "jni_util.h"
+
 #include <windows.h>
 #include <Sddl.h>
 #include <string.h>
 
-#include "jni.h"
-#include "jni_util.h"
-
 #include "sun_tools_attach_VirtualMachineImpl.h"
 
-
 /* kernel32 */
 typedef HINSTANCE (WINAPI* GetModuleHandleFunc) (LPCTSTR);
 typedef FARPROC (WINAPI* GetProcAddressFunc)(HMODULE, LPCSTR);
@@ -303,9 +302,7 @@
     LocalFree(sa.lpSecurityDescriptor);
 
     if (hPipe == INVALID_HANDLE_VALUE) {
-        char msg[256];
-        _snprintf(msg, sizeof(msg), "CreateNamedPipe failed: %d", GetLastError());
-        JNU_ThrowIOExceptionWithLastError(env, msg);
+        JNU_ThrowIOExceptionWithLastError(env, "CreateNamedPipe failed");
     }
     return (jlong)hPipe;
 }
@@ -318,7 +315,7 @@
 JNIEXPORT void JNICALL Java_sun_tools_attach_VirtualMachineImpl_closePipe
   (JNIEnv *env, jclass cls, jlong hPipe)
 {
-    CloseHandle( (HANDLE)hPipe );
+    CloseHandle((HANDLE)hPipe);
 }
 
 /*
@@ -430,7 +427,7 @@
             if ((*env)->ExceptionOccurred(env)) return;
         }
     }
-    for (i=argsLen; i<MAX_ARGS; i++) {
+    for (i = argsLen; i < MAX_ARGS; i++) {
         data.arg[i][0] = '\0';
     }