From 18d00dae90999bde4bbb41ba2e0b23ede4fe2583 Mon Sep 17 00:00:00 2001 From: Marcin Olszewski Date: Tue, 11 Apr 2023 16:35:58 +0200 Subject: [PATCH 1/7] Necessary changes to reuse in gprofiler: - make sure fdtransfer parent process finishes, - support prefix directory for async-profiler sharedlib --- src/launcher/main.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/launcher/main.cpp b/src/launcher/main.cpp index ea3a64506..b510e9c43 100644 --- a/src/launcher/main.cpp +++ b/src/launcher/main.cpp @@ -205,6 +205,7 @@ class String { static String action = "collect"; +static const String empty; static String file, logfile, output, params, format, fdtransfer, libpath; static bool use_tmp_file = false; static int duration = 60; @@ -474,6 +475,9 @@ int main(int argc, const char** argv) { // The last argument is the application name as it would appear in the jps tool pid = jps("jps -J-XX:+PerfDisableSharedMem", arg.str()); + } else if (arg == "-L" || arg == "--lib-prefix") { + libpath = String(args.next()) << "/libasyncProfiler.so"; + } else { fprintf(stderr, "Unrecognized option: %s\n", arg.str()); return 1; @@ -486,7 +490,9 @@ int main(int argc, const char** argv) { } setup_output_files(pid); - setup_lib_path(); + if (libpath == empty) { + setup_lib_path(); + } if (action == "collect") { run_fdtransfer(pid, fdtransfer); From b84bd80a4469daa6c7b022c7877131c066881ede Mon Sep 17 00:00:00 2001 From: Marcin Olszewski Date: Fri, 14 Apr 2023 15:08:23 +0200 Subject: [PATCH 2/7] Expose fdtransfer, jattach and jcmd and support lib-prefix --- Makefile | 2 +- src/launcher/main.cpp | 90 ++++++++++++++++++++++++++++++++++++------- 2 files changed, 77 insertions(+), 15 deletions(-) diff --git a/Makefile b/Makefile index e1d799540..aaba8d061 100644 --- a/Makefile +++ b/Makefile @@ -118,7 +118,7 @@ build/%: mkdir -p $@ build/$(LAUNCHER): src/launcher/* src/jattach/* src/fdtransfer.h - $(CC) $(CPPFLAGS) $(CFLAGS) -DPROFILER_VERSION=\"$(PROFILER_VERSION)\" -DSUPPRESS_OUTPUT -o $@ src/launcher/*.cpp src/jattach/*.c + $(CC) $(CPPFLAGS) $(CFLAGS) -DPROFILER_VERSION=\"$(PROFILER_VERSION)\" -o $@ src/launcher/*.cpp src/jattach/*.c strip $@ PROFILER_FLAGS=-static-libgcc diff --git a/src/launcher/main.cpp b/src/launcher/main.cpp index b510e9c43..fc71283e1 100644 --- a/src/launcher/main.cpp +++ b/src/launcher/main.cpp @@ -51,6 +51,10 @@ static const char USAGE_STRING[] = " list list profiling events supported by the target JVM\n" " collect collect profile for the specified period of time\n" " and then stop (default action)\n" + " fdtransfer start fdtransfer to serve perf requests on behalf of profiled process\n" + " jattach invoke jattach directly; requires --jattach-cmd,\n" + " ignores all arguments except --lib-prefix\n" + "\n" "Options:\n" " -e event profiling event: cpu|alloc|lock|cache-misses etc.\n" " -d duration run profiling for seconds\n" @@ -87,6 +91,12 @@ static const char USAGE_STRING[] = " --jfrsync config synchronize profiler with JFR recording\n" " --fdtransfer use fdtransfer to serve perf requests\n" " from the non-privileged target\n" + " --fd-path string use specified path for fdtransfer to listen at\n" + " --jattach-cmd string\n" + " arguments to use with jattach action\n" + " -L|--lib-prefix string\n" + " path prefix to prepend to shared lib\n" + " --fd-path string socket path for fdtransfer to bind to\n" "\n" " is a numeric process ID of the target JVM\n" " or 'jps' keyword to find running JVM automatically\n" @@ -170,6 +180,10 @@ class String { return strcmp(_str, other._str) == 0; } + bool operator!=(const String& other) const { + return strcmp(_str, other._str) != 0; + } + String& operator<<(const char* tail) { size_t len = strlen(_str); _str = (char*)realloc(_str, len + strlen(tail) + 1); @@ -205,7 +219,9 @@ class String { static String action = "collect"; -static const String empty; +static const String kEmpty; +static const String kJattachLoad = "load"; +static const String kJattachJcmd = "jcmd"; static String file, logfile, output, params, format, fdtransfer, libpath; static bool use_tmp_file = false; static int duration = 60; @@ -333,26 +349,37 @@ static void run_fdtransfer(int pid, String& fdtransfer) { } } -static void run_jattach(int pid, String& cmd) { +static void run_jattach(int pid, const String& verb, String& cmd) { pid_t child = fork(); if (child == -1) { error("fork failed", errno); } if (child == 0) { - const char* argv[] = {"load", libpath.str(), libpath.str()[0] == '/' ? "true" : "false", cmd.str()}; - exit(jattach(pid, 4, argv)); + const char** argv; + int argc; + int ret; + String pidstr; + pidstr << pid; + if (verb == kJattachLoad) { + const char* args[] = {kJattachLoad.str(), libpath.str(), libpath.str()[0] == '/' ? "true" : "false", cmd.str()}; + ret = jattach(pid, 4, args); + } else if (verb == kJattachJcmd) { + const char* args[] = {kJattachJcmd.str(), cmd.str()}; + ret = jattach(pid, 2, args); + } + exit(ret); } else { int ret = wait_for_exit(child); if (ret != 0) { if (WEXITSTATUS(ret) == 255) { fprintf(stderr, "Target JVM failed to load %s\n", libpath.str()); } - print_file(logfile, STDERR_FILENO); + if (logfile != kEmpty) print_file(logfile, STDERR_FILENO); exit(WEXITSTATUS(ret)); } - print_file(logfile, STDERR_FILENO); + if (logfile != kEmpty) print_file(logfile, STDERR_FILENO); if (use_tmp_file) print_file(file, STDOUT_FILENO); } } @@ -360,11 +387,13 @@ static void run_jattach(int pid, String& cmd) { int main(int argc, const char** argv) { Args args(argc, argv); + String jattach_cmd; while (args.hasNext()) { String arg = args.next(); if (arg == "start" || arg == "resume" || arg == "stop" || arg == "dump" || arg == "check" || - arg == "status" || arg == "meminfo" || arg == "list" || arg == "collect") { + arg == "status" || arg == "meminfo" || arg == "list" || arg == "collect" || + arg == "fdtransfer" || arg == "jattach" || arg == "jcmd") { action = arg; } else if (arg == "-h" || arg == "--help") { @@ -457,12 +486,20 @@ int main(int argc, const char** argv) { params << "," << (arg.str() + 2) << "=" << args.next(); if (action == "collect") action = "start"; + } else if (arg == "--fd-path") { + fdtransfer = String(args.next()); + } else if (arg == "--fdtransfer") { char buf[64]; - snprintf(buf, sizeof(buf), "@async-profiler-%d-%08x", getpid(), (unsigned int)time_micros()); - fdtransfer = buf; + if (fdtransfer == kEmpty) { + snprintf(buf, sizeof(buf), "@async-profiler-%d-%08x", getpid(), (unsigned int)time_micros()); + fdtransfer = buf; + } params << ",fdtransfer=" << fdtransfer; + } else if (arg == "--jattach-cmd") { + jattach_cmd = String(args.next()); + } else if (arg.str()[0] >= '0' && arg.str()[0] <= '9' && pid == 0) { pid = atoi(arg.str()); @@ -489,14 +526,19 @@ int main(int argc, const char** argv) { return 1; } - setup_output_files(pid); - if (libpath == empty) { + if (jattach_cmd == kEmpty) { + setup_output_files(pid); + } else if (params != kEmpty) { + fprintf(stderr, "Warning: --jattach-cmd was given, these parameters will be ignored: %s\n", params.str()); + } + + if (libpath == kEmpty) { setup_lib_path(); } if (action == "collect") { run_fdtransfer(pid, fdtransfer); - run_jattach(pid, String("start,file=") << file << "," << output << format << params << ",log=" << logfile); + run_jattach(pid, kJattachLoad, String("start,file=") << file << "," << output << format << params << ",log=" << logfile); fprintf(stderr, "Profiling for %d seconds\n", duration); end_time = time_micros() + duration * 1000000ULL; @@ -514,10 +556,30 @@ int main(int argc, const char** argv) { signal(SIGINT, SIG_DFL); fprintf(stderr, "Done\n"); - run_jattach(pid, String("stop,file=") << file << "," << output << format << ",log=" << logfile); + run_jattach(pid, kJattachLoad, String("stop,file=") << file << "," << output << format << ",log=" << logfile); + } else if (action == "fdtransfer") { + if (params != kEmpty) { + fprintf(stderr, "Warning: action fdtransfer was given, these parameters will be ignored: %s\n", params.str()); + } + run_fdtransfer(pid, fdtransfer); + + } else if (action == "jattach") { + if (jattach_cmd == kEmpty) { + fprintf(stderr, "Action jattach was given, missing required --jattach-cmd argument\n"); + return 1; + } + run_jattach(pid, kJattachLoad, jattach_cmd); + + } else if (action == "jcmd") { + if (jattach_cmd == kEmpty) { + fprintf(stderr, "Action jcmd was given, missing required --jattach-cmd argument\n"); + return 1; + } + run_jattach(pid, kJattachJcmd, jattach_cmd); + } else { if (action == "start" || action == "resume") run_fdtransfer(pid, fdtransfer); - run_jattach(pid, String(action) << ",file=" << file << "," << output << format << params << ",log=" << logfile); + run_jattach(pid, kJattachLoad, String(action) << ",file=" << file << "," << output << format << params << ",log=" << logfile); } return 0; From a0205eb8da773521ed958f59c84407534de29494 Mon Sep 17 00:00:00 2001 From: Marcin Olszewski Date: Fri, 28 Apr 2023 18:48:50 +0200 Subject: [PATCH 3/7] Support timeout for fdtransfer command --- src/launcher/fdtransferServer.h | 4 ++-- src/launcher/fdtransferServer_linux.cpp | 4 ++-- src/launcher/main.cpp | 16 ++++++++++------ 3 files changed, 14 insertions(+), 10 deletions(-) diff --git a/src/launcher/fdtransferServer.h b/src/launcher/fdtransferServer.h index d234e8cc8..07ce4ff3e 100644 --- a/src/launcher/fdtransferServer.h +++ b/src/launcher/fdtransferServer.h @@ -36,7 +36,7 @@ class FdTransferServer { public: static bool supported() { return true; } - static bool runOnce(int pid, const char *path); + static bool runOnce(int pid, const char *path, unsigned int timeout); static bool runLoop(const char *path); }; @@ -46,7 +46,7 @@ class FdTransferServer { public: static bool supported() { return false; } - static bool runOnce(int pid, const char *path) { return false; } + static bool runOnce(int pid, const char *path, unsigned int timeout) { return false; } static bool runLoop(const char *path) { return false; } }; diff --git a/src/launcher/fdtransferServer_linux.cpp b/src/launcher/fdtransferServer_linux.cpp index b5c3f7cd4..193e32f5a 100644 --- a/src/launcher/fdtransferServer_linux.cpp +++ b/src/launcher/fdtransferServer_linux.cpp @@ -260,7 +260,7 @@ bool FdTransferServer::sendFd(int fd, struct fd_response *resp, size_t resp_size return true; } -bool FdTransferServer::runOnce(int pid, const char *path) { +bool FdTransferServer::runOnce(int pid, const char *path, unsigned int timeout) { // get its nspid prior to moving to its PID namespace. int nspid; uid_t target_uid; @@ -287,7 +287,7 @@ bool FdTransferServer::runOnce(int pid, const char *path) { } } - if (!bindServer(&sun, addrlen, 30)) { + if (!bindServer(&sun, addrlen, timeout)) { return false; } diff --git a/src/launcher/main.cpp b/src/launcher/main.cpp index fc71283e1..31c0d5d7c 100644 --- a/src/launcher/main.cpp +++ b/src/launcher/main.cpp @@ -107,6 +107,7 @@ static const char USAGE_STRING[] = " " APP_BINARY " stop -o flat jps\n" " " APP_BINARY " -d 5 -e alloc MyAppName\n"; +static const unsigned int DEFAULT_FDTRANSFER_TIMEOUT = 30; extern "C" int jattach(int pid, int argc, const char** argv); @@ -227,6 +228,7 @@ static bool use_tmp_file = false; static int duration = 60; static int pid = 0; static volatile unsigned long long end_time; +static unsigned int timeout = DEFAULT_FDTRANSFER_TIMEOUT; static void sigint_handler(int sig) { end_time = 0; @@ -331,7 +333,7 @@ static int jps(const char* cmd, const char* app_name = NULL) { return pid; } -static void run_fdtransfer(int pid, String& fdtransfer) { +static void run_fdtransfer(int pid, String& fdtransfer, unsigned int timeout) { if (!FdTransferServer::supported() || fdtransfer == "") return; pid_t child = fork(); @@ -340,7 +342,7 @@ static void run_fdtransfer(int pid, String& fdtransfer) { } if (child == 0) { - exit(FdTransferServer::runOnce(pid, fdtransfer.str()) ? 0 : 1); + exit(FdTransferServer::runOnce(pid, fdtransfer.str(), timeout) ? 0 : 1); } else { int ret = wait_for_exit(child); if (ret != 0) { @@ -483,7 +485,9 @@ int main(int argc, const char** argv) { output = "jfr"; } else if (arg == "--timeout" || arg == "--loop") { - params << "," << (arg.str() + 2) << "=" << args.next(); + const char* value = args.next(); + params << "," << (arg.str() + 2) << "=" << value; + timeout = atoi(value); if (action == "collect") action = "start"; } else if (arg == "--fd-path") { @@ -537,7 +541,7 @@ int main(int argc, const char** argv) { } if (action == "collect") { - run_fdtransfer(pid, fdtransfer); + run_fdtransfer(pid, fdtransfer, timeout); run_jattach(pid, kJattachLoad, String("start,file=") << file << "," << output << format << params << ",log=" << logfile); fprintf(stderr, "Profiling for %d seconds\n", duration); @@ -561,7 +565,7 @@ int main(int argc, const char** argv) { if (params != kEmpty) { fprintf(stderr, "Warning: action fdtransfer was given, these parameters will be ignored: %s\n", params.str()); } - run_fdtransfer(pid, fdtransfer); + run_fdtransfer(pid, fdtransfer, timeout); } else if (action == "jattach") { if (jattach_cmd == kEmpty) { @@ -578,7 +582,7 @@ int main(int argc, const char** argv) { run_jattach(pid, kJattachJcmd, jattach_cmd); } else { - if (action == "start" || action == "resume") run_fdtransfer(pid, fdtransfer); + if (action == "start" || action == "resume") run_fdtransfer(pid, fdtransfer, timeout); run_jattach(pid, kJattachLoad, String(action) << ",file=" << file << "," << output << format << params << ",log=" << logfile); } From cc438aab489df27bbd9a354861269ab7815be7d3 Mon Sep 17 00:00:00 2001 From: Marcin Olszewski Date: Thu, 4 May 2023 13:52:47 +0200 Subject: [PATCH 4/7] Address comments in review --- src/launcher/main.cpp | 35 ++++++++++++++--------------------- 1 file changed, 14 insertions(+), 21 deletions(-) diff --git a/src/launcher/main.cpp b/src/launcher/main.cpp index 31c0d5d7c..c760fb189 100644 --- a/src/launcher/main.cpp +++ b/src/launcher/main.cpp @@ -53,7 +53,7 @@ static const char USAGE_STRING[] = " and then stop (default action)\n" " fdtransfer start fdtransfer to serve perf requests on behalf of profiled process\n" " jattach invoke jattach directly; requires --jattach-cmd,\n" - " ignores all arguments except --lib-prefix\n" + " ignores all arguments except --lib-path\n" "\n" "Options:\n" " -e event profiling event: cpu|alloc|lock|cache-misses etc.\n" @@ -91,11 +91,10 @@ static const char USAGE_STRING[] = " --jfrsync config synchronize profiler with JFR recording\n" " --fdtransfer use fdtransfer to serve perf requests\n" " from the non-privileged target\n" - " --fd-path string use specified path for fdtransfer to listen at\n" " --jattach-cmd string\n" " arguments to use with jattach action\n" - " -L|--lib-prefix string\n" - " path prefix to prepend to shared lib\n" + " -L|--lib-path string\n" + " path to async-profiler's shared lib\n" " --fd-path string socket path for fdtransfer to bind to\n" "\n" " is a numeric process ID of the target JVM\n" @@ -182,7 +181,7 @@ class String { } bool operator!=(const String& other) const { - return strcmp(_str, other._str) != 0; + return !(*this == other); } String& operator<<(const char* tail) { @@ -228,6 +227,7 @@ static bool use_tmp_file = false; static int duration = 60; static int pid = 0; static volatile unsigned long long end_time; +// gprofiler-specific: holds timeout value for fdtransfer command static unsigned int timeout = DEFAULT_FDTRANSFER_TIMEOUT; static void sigint_handler(int sig) { @@ -358,19 +358,13 @@ static void run_jattach(int pid, const String& verb, String& cmd) { } if (child == 0) { - const char** argv; - int argc; - int ret; - String pidstr; - pidstr << pid; if (verb == kJattachLoad) { const char* args[] = {kJattachLoad.str(), libpath.str(), libpath.str()[0] == '/' ? "true" : "false", cmd.str()}; - ret = jattach(pid, 4, args); + exit(jattach(pid, 4, args)); } else if (verb == kJattachJcmd) { const char* args[] = {kJattachJcmd.str(), cmd.str()}; - ret = jattach(pid, 2, args); + exit(jattach(pid, 2, args)); } - exit(ret); } else { int ret = wait_for_exit(child); if (ret != 0) { @@ -487,6 +481,7 @@ int main(int argc, const char** argv) { } else if (arg == "--timeout" || arg == "--loop") { const char* value = args.next(); params << "," << (arg.str() + 2) << "=" << value; + // gprofiler-specific: borrow timeout parameter to configure socket timeout for fdtransfer action timeout = atoi(value); if (action == "collect") action = "start"; @@ -495,10 +490,8 @@ int main(int argc, const char** argv) { } else if (arg == "--fdtransfer") { char buf[64]; - if (fdtransfer == kEmpty) { - snprintf(buf, sizeof(buf), "@async-profiler-%d-%08x", getpid(), (unsigned int)time_micros()); - fdtransfer = buf; - } + snprintf(buf, sizeof(buf), "@async-profiler-%d-%08x", getpid(), (unsigned int)time_micros()); + fdtransfer = buf; params << ",fdtransfer=" << fdtransfer; } else if (arg == "--jattach-cmd") { @@ -516,8 +509,8 @@ int main(int argc, const char** argv) { // The last argument is the application name as it would appear in the jps tool pid = jps("jps -J-XX:+PerfDisableSharedMem", arg.str()); - } else if (arg == "-L" || arg == "--lib-prefix") { - libpath = String(args.next()) << "/libasyncProfiler.so"; + } else if (arg == "-L" || arg == "--lib-path") { + libpath = String(args.next()); } else { fprintf(stderr, "Unrecognized option: %s\n", arg.str()); @@ -541,7 +534,7 @@ int main(int argc, const char** argv) { } if (action == "collect") { - run_fdtransfer(pid, fdtransfer, timeout); + run_fdtransfer(pid, fdtransfer, 0); run_jattach(pid, kJattachLoad, String("start,file=") << file << "," << output << format << params << ",log=" << logfile); fprintf(stderr, "Profiling for %d seconds\n", duration); @@ -582,7 +575,7 @@ int main(int argc, const char** argv) { run_jattach(pid, kJattachJcmd, jattach_cmd); } else { - if (action == "start" || action == "resume") run_fdtransfer(pid, fdtransfer, timeout); + if (action == "start" || action == "resume") run_fdtransfer(pid, fdtransfer, 0); run_jattach(pid, kJattachLoad, String(action) << ",file=" << file << "," << output << format << params << ",log=" << logfile); } From dbc591843a9b8cc0c847583ff826140d3b09e484 Mon Sep 17 00:00:00 2001 From: Marcin Olszewski Date: Thu, 4 May 2023 14:30:27 +0200 Subject: [PATCH 5/7] Fix Makefile --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index aaba8d061..053e6eda8 100644 --- a/Makefile +++ b/Makefile @@ -155,7 +155,7 @@ build/$(CONVERTER_JAR): $(CONVERTER_SOURCES) $(RESOURCES) $(RM) -r build/converter %.class: %.java - $(JAVAC) --source $(JAVA_TARGET) -target $(JAVA_TARGET) -Xlint:-options -g:none $^ + $(JAVAC) -source $(JAVA_TARGET) -target $(JAVA_TARGET) -Xlint:-options -g:none $^ test: all test/smoke-test.sh From 951442849adbd723ebd92c3997b9ecf9c6978c41 Mon Sep 17 00:00:00 2001 From: Marcin Olszewski Date: Fri, 5 May 2023 14:00:27 +0200 Subject: [PATCH 6/7] Link async-profiler launcher statically, fixing dependency on glibc and startup on musl-based systems --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 053e6eda8..e70949107 100644 --- a/Makefile +++ b/Makefile @@ -118,7 +118,7 @@ build/%: mkdir -p $@ build/$(LAUNCHER): src/launcher/* src/jattach/* src/fdtransfer.h - $(CC) $(CPPFLAGS) $(CFLAGS) -DPROFILER_VERSION=\"$(PROFILER_VERSION)\" -o $@ src/launcher/*.cpp src/jattach/*.c + $(CC) $(CPPFLAGS) $(CFLAGS) -static -DPROFILER_VERSION=\"$(PROFILER_VERSION)\" -o $@ src/launcher/*.cpp src/jattach/*.c strip $@ PROFILER_FLAGS=-static-libgcc From 355000e0cbf8888730628c7247c6eccf940f910b Mon Sep 17 00:00:00 2001 From: Marcin Olszewski Date: Wed, 10 May 2023 11:59:11 +0200 Subject: [PATCH 7/7] Apply suggestions in review --- src/launcher/main.cpp | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/src/launcher/main.cpp b/src/launcher/main.cpp index c760fb189..c2455e964 100644 --- a/src/launcher/main.cpp +++ b/src/launcher/main.cpp @@ -228,7 +228,7 @@ static int duration = 60; static int pid = 0; static volatile unsigned long long end_time; // gprofiler-specific: holds timeout value for fdtransfer command -static unsigned int timeout = DEFAULT_FDTRANSFER_TIMEOUT; +static unsigned int fdtransfer_timeout = DEFAULT_FDTRANSFER_TIMEOUT; static void sigint_handler(int sig) { end_time = 0; @@ -364,7 +364,7 @@ static void run_jattach(int pid, const String& verb, String& cmd) { } else if (verb == kJattachJcmd) { const char* args[] = {kJattachJcmd.str(), cmd.str()}; exit(jattach(pid, 2, args)); - } + } else { exit (1); } } else { int ret = wait_for_exit(child); if (ret != 0) { @@ -479,12 +479,13 @@ int main(int argc, const char** argv) { output = "jfr"; } else if (arg == "--timeout" || arg == "--loop") { - const char* value = args.next(); - params << "," << (arg.str() + 2) << "=" << value; - // gprofiler-specific: borrow timeout parameter to configure socket timeout for fdtransfer action - timeout = atoi(value); + params << "," << (arg.str() + 2) << "=" << args.next(); + if (action == "collect") action = "start"; + } else if (arg == "--fdtransfer-timeout") { + fdtransfer_timeout = atoi(args.next()); + } else if (arg == "--fd-path") { fdtransfer = String(args.next()); @@ -526,7 +527,8 @@ int main(int argc, const char** argv) { if (jattach_cmd == kEmpty) { setup_output_files(pid); } else if (params != kEmpty) { - fprintf(stderr, "Warning: --jattach-cmd was given, these parameters will be ignored: %s\n", params.str()); + fprintf(stderr, "Argument --jattach-cmd was given, need no other parameters\n"); + return 1; } if (libpath == kEmpty) { @@ -556,9 +558,10 @@ int main(int argc, const char** argv) { run_jattach(pid, kJattachLoad, String("stop,file=") << file << "," << output << format << ",log=" << logfile); } else if (action == "fdtransfer") { if (params != kEmpty) { - fprintf(stderr, "Warning: action fdtransfer was given, these parameters will be ignored: %s\n", params.str()); + fprintf(stderr, "Action fdtransfer was given, all parameters are to be passed with --jattach-cmd\n"); + return 1; } - run_fdtransfer(pid, fdtransfer, timeout); + run_fdtransfer(pid, fdtransfer, fdtransfer_timeout); } else if (action == "jattach") { if (jattach_cmd == kEmpty) {