]> git.sven.stormbind.net Git - sven/jattach.git/blobdiff - src/posix/jattach_hotspot.c
New upstream version 2.2
[sven/jattach.git] / src / posix / jattach_hotspot.c
index e23e4609a0e3dcb31e38ad1e12475f31b1413cea..68d8805c05f9005644e9e9c146fff71f7bae03ee 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 2021 Andrei Pangin
+ * Copyright jattach authors
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -27,6 +27,8 @@
 #include "psutil.h"
 
 
+extern int mnt_changed;
+
 // Check if remote JVM has already opened socket for Dynamic Attach
 static int check_socket(int pid) {
     char path[MAX_PATH];
@@ -46,7 +48,7 @@ static uid_t get_file_owner(const char* path) {
 // HotSpot will start Attach listener in response to SIGQUIT if it sees .attach_pid file
 static int start_attach_mechanism(int pid, int nspid) {
     char path[MAX_PATH];
-    snprintf(path, sizeof(path), "/proc/%d/cwd/.attach_pid%d", nspid, nspid);
+    snprintf(path, sizeof(path), "/proc/%d/cwd/.attach_pid%d", mnt_changed > 0 ? nspid : pid, nspid);
 
     int fd = creat(path, 0660);
     if (fd == -1 || (close(fd) == 0 && get_file_owner(path) != geteuid())) {
@@ -102,23 +104,37 @@ static int connect_socket(int pid) {
 
 // Send command with arguments to socket
 static int write_command(int fd, int argc, char** argv) {
+    char buf[8192];
+    const char* const limit = buf + sizeof(buf);
+
+    // jcmd has 2 arguments maximum; merge excessive arguments into one
+    int cmd_args = argc >= 2 && strcmp(argv[0], "jcmd") == 0 ? 2 : argc >= 4 ? 4 : argc;
+
     // Protocol version
-    if (write(fd, "1", 2) <= 0) {
-        return -1;
-    }
+    char* p = stpncpy(buf, "1", sizeof(buf)) + 1;
 
     int i;
-    for (i = 0; i < 4; i++) {
-        const char* arg = i < argc ? argv[i] : "";
-        if (write(fd, arg, strlen(arg) + 1) <= 0) {
+    for (i = 0; i < argc && p < limit; i++) {
+        if (i >= cmd_args) p[-1] = ' ';
+        p = stpncpy(p, argv[i], limit - p) + 1;
+    }
+    for (i = cmd_args; i < 4 && p < limit; i++) {
+        *p++ = 0;
+    }
+
+    const char* q = p < limit ? p : limit;
+    for (p = buf; p < q; ) {
+        ssize_t bytes = write(fd, p, q - p);
+        if (bytes <= 0) {
             return -1;
         }
+        p += (size_t)bytes;
     }
     return 0;
 }
 
 // Mirror response from remote JVM to stdout
-static int read_response(int fd, int argc, char** argv) {
+static int read_response(int fd, int argc, char** argv, int print_output) {
     char buf[8192];
     ssize_t bytes = read(fd, buf, sizeof(buf) - 1);
     if (bytes == 0) {
@@ -146,18 +162,20 @@ static int read_response(int fd, int argc, char** argv) {
         result = atoi(strncmp(buf + 2, "return code: ", 13) == 0 ? buf + 15 : buf + 2);
     }
 
-    // Mirror JVM response to stdout
-    printf("JVM response code = ");
-    do {
-        fwrite(buf, 1, bytes, stdout);
-        bytes = read(fd, buf, sizeof(buf));
-    } while (bytes > 0);
-    printf("\n");
+    if (print_output) {
+        // Mirror JVM response to stdout
+        printf("JVM response code = ");
+        do {
+            fwrite(buf, 1, bytes, stdout);
+            bytes = read(fd, buf, sizeof(buf));
+        } while (bytes > 0);
+        printf("\n");
+    }
 
     return result;
 }
 
-int jattach_hotspot(int pid, int nspid, int argc, char** argv) {
+int jattach_hotspot(int pid, int nspid, int argc, char** argv, int print_output) {
     if (check_socket(nspid) != 0 && start_attach_mechanism(pid, nspid) != 0) {
         perror("Could not start attach mechanism");
         return 1;
@@ -169,7 +187,9 @@ int jattach_hotspot(int pid, int nspid, int argc, char** argv) {
         return 1;
     }
 
-    printf("Connected to remote JVM\n");
+    if (print_output) {
+        printf("Connected to remote JVM\n");
+    }
 
     if (write_command(fd, argc, argv) != 0) {
         perror("Error writing to socket");
@@ -177,7 +197,7 @@ int jattach_hotspot(int pid, int nspid, int argc, char** argv) {
         return 1;
     }
 
-    int result = read_response(fd, argc, argv);
+    int result = read_response(fd, argc, argv, print_output);
     close(fd);
 
     return result;