From 441d8b75a0c8f3ab3b95c88376ff153a5a569d99 Mon Sep 17 00:00:00 2001 From: "Bruce A. Mah" Date: Fri, 24 Jan 2014 16:42:10 -0800 Subject: [PATCH] Add support for writing the PID to a file in server mode. This is specified with the -I or --pidfile option. Issue: 120 (PID file support) --- RELEASE_NOTES | 3 +++ src/iperf.h | 1 + src/iperf3.1 | 3 +++ src/iperf_api.c | 40 +++++++++++++++++++++++++++++++++++++++- src/iperf_api.h | 5 ++++- src/iperf_error.c | 7 ++++++- src/locale.c | 1 + src/main.c | 5 +++++ 8 files changed, 62 insertions(+), 3 deletions(-) diff --git a/RELEASE_NOTES b/RELEASE_NOTES index 954529e..4a8f641 100644 --- a/RELEASE_NOTES +++ b/RELEASE_NOTES @@ -1,5 +1,8 @@ == iperf 3.?.? ????-??-?? == * Setting CPU affinity now works on FreeBSD. + * Added -I flag for server to write a PID file, mostly useful for + daemon mode. + * Bug fixes. == iperf 3.0.1 2014-01-10 == * Added the following new flags diff --git a/src/iperf.h b/src/iperf.h index f391ea8..188f06a 100644 --- a/src/iperf.h +++ b/src/iperf.h @@ -172,6 +172,7 @@ struct iperf_test #endif char *title; /* -T option */ char *congestion; /* -C option */ + char *pidfile; /* -P option */ int ctrl_sck; int listener; diff --git a/src/iperf3.1 b/src/iperf3.1 index c835028..f56d279 100644 --- a/src/iperf3.1 +++ b/src/iperf3.1 @@ -69,6 +69,9 @@ run in server mode .TP .BR -D ", " --daemon " " run the server in background as a daemon +.TP +.BR -I ", " --pidfile " \fIfile\fR" +write a file with the process ID, most useful when running as a daemon. .SH "CLIENT SPECIFIC OPTIONS" .TP diff --git a/src/iperf_api.c b/src/iperf_api.c index d27c9c1..47b011a 100644 --- a/src/iperf_api.c +++ b/src/iperf_api.c @@ -545,6 +545,7 @@ iperf_parse_arguments(struct iperf_test *test, int argc, char **argv) #if defined(linux) && defined(TCP_CONGESTION) {"linux-congestion", required_argument, NULL, 'C'}, #endif + {"pidfile", required_argument, NULL, 'I'}, {"debug", no_argument, NULL, 'd'}, {"help", no_argument, NULL, 'h'}, {NULL, 0, NULL, 0} @@ -559,7 +560,7 @@ iperf_parse_arguments(struct iperf_test *test, int argc, char **argv) blksize = 0; server_flag = client_flag = rate_flag = duration_flag = 0; - while ((flag = getopt_long(argc, argv, "p:f:i:DVJvsc:ub:t:n:k:l:P:Rw:B:M:N46S:L:ZO:F:A:T:C:dh", longopts, NULL)) != -1) { + while ((flag = getopt_long(argc, argv, "p:f:i:DVJvsc:ub:t:n:k:l:P:Rw:B:M:N46S:L:ZO:F:A:T:C:dI:h", longopts, NULL)) != -1) { switch (flag) { case 'p': test->server_port = atoi(optarg); @@ -762,6 +763,10 @@ iperf_parse_arguments(struct iperf_test *test, int argc, char **argv) case 'd': test->debug = 1; break; + case 'I': + test->pidfile = strdup(optarg); + server_flag = 1; + break; case 'h': default: usage_long(); @@ -2383,6 +2388,39 @@ iperf_got_sigend(struct iperf_test *test) iperf_errexit(test, "interrupt - %s", iperf_strerror(i_errno)); } +/* Try to write a PID file if requested, return -1 on an error. */ +int +iperf_create_pidfile(struct iperf_test *test) +{ + if (test->pidfile) { + int fd; + char buf[8]; + fd = open(test->pidfile, O_WRONLY | O_CREAT | O_TRUNC, 0666); + if (fd < 0) { + return -1; + } + snprintf(buf, sizeof(buf), "%d", getpid()); /* no trailing newline */ + if (write(fd, buf, strlen(buf) + 1) < 0) { + return -1; + } + if (close(fd) < 0) { + return -1; + }; + } + return 0; +} + +/* Get rid of a PID file, return -1 on error. */ +int +iperf_delete_pidfile(struct iperf_test *test) +{ + if (test->pidfile) { + if (unlink(test->pidfile) < 0) { + return -1; + } + } + return 0; +} int iperf_json_start(struct iperf_test *test) diff --git a/src/iperf_api.h b/src/iperf_api.h index 1982836..bc68b96 100644 --- a/src/iperf_api.h +++ b/src/iperf_api.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009-2013, The Regents of the University of California, + * Copyright (c) 2009-2014, The Regents of the University of California, * through Lawrence Berkeley National Laboratory (subject to receipt of any * required approvals from the U.S. Dept. of Energy). All rights reserved. * @@ -207,6 +207,8 @@ int iperf_server_listen(struct iperf_test *); int iperf_accept(struct iperf_test *); int iperf_handle_message_server(struct iperf_test *); void iperf_test_reset(struct iperf_test *); +int iperf_create_pidfile(struct iperf_test *); +int iperf_delete_pidfile(struct iperf_test *); /* JSON output routines. */ int iperf_json_start(struct iperf_test *); @@ -280,6 +282,7 @@ enum { IEAFFINITY = 132, // Unable to set CPU affinity (check perror) IEDAEMON = 133, // Unable to become a daemon process IESETCONGESTION = 134, // Unable to set TCP_CONGESTION + IEPIDFILE = 135, // Unable to write PID file /* Stream errors */ IECREATESTREAM = 200, // Unable to create a new stream (check herror/perror) IEINITSTREAM = 201, // Unable to initialize stream (check herror/perror) diff --git a/src/iperf_error.c b/src/iperf_error.c index 04afed0..645df48 100644 --- a/src/iperf_error.c +++ b/src/iperf_error.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009-2013, The Regents of the University of California, + * Copyright (c) 2009-2014, The Regents of the University of California, * through Lawrence Berkeley National Laboratory (subject to receipt of any * required approvals from the U.S. Dept. of Energy). All rights reserved. * @@ -47,6 +47,7 @@ iperf_errexit(struct iperf_test *test, const char *format, ...) } else fprintf(stderr, "iperf3: %s\n", str); va_end(argp); + iperf_delete_pidfile(test); exit(1); } @@ -294,6 +295,10 @@ iperf_strerror(int i_errno) snprintf(errstr, len, "unable to set TCP_CONGESTION: " "Supplied congestion control algorithm not supported on this host"); break; + case IEPIDFILE: + snprintf(errstr, len, "unable to write PID file"); + perr = 1; + break; } if (herr || perr) diff --git a/src/locale.c b/src/locale.c index 4471e6c..84c1953 100644 --- a/src/locale.c +++ b/src/locale.c @@ -84,6 +84,7 @@ const char usage_longstr[] = "Usage: iperf [-s|-c host] [options]\n" "Server specific:\n" " -s, --server run in server mode\n" " -D, --daemon run the server as a daemon\n" + " -I, --pidfile file write PID file\n" "Client specific:\n" " -c, --client run in client mode, connecting to \n" " -u, --udp use UDP rather than TCP\n" diff --git a/src/main.c b/src/main.c index 66efd6a..6b49fb2 100644 --- a/src/main.c +++ b/src/main.c @@ -112,6 +112,10 @@ run(struct iperf_test *test) } } consecutive_errors = 0; + if (iperf_create_pidfile(test) < 0) { + i_errno = IEPIDFILE; + iperf_errexit(test, "error - %s", iperf_strerror(i_errno)); + } for (;;) { if (iperf_run_server(test) < 0) { iperf_err(test, "error - %s", iperf_strerror(i_errno)); @@ -125,6 +129,7 @@ run(struct iperf_test *test) consecutive_errors = 0; iperf_reset_test(test); } + iperf_delete_pidfile(test); break; case 'c': if (iperf_run_client(test) < 0)