From 0dbe3d28f7e2716e568ef36c8fa4d3c0964239f0 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Rafa=C5=82=20Mi=C5=82ecki?= Date: Sun, 7 Oct 2018 14:17:50 +0200 Subject: [PATCH] iperf: fix --daemon option MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Support for -D got broken in the 2.0.11 release by the upstream commit 218d8c667944 ("first pass L2 mode w/UDP checks, v4 only"). After that commit clients were still able to connect but no traffic was passed. It was reported and is fixed now in the upstream git repository. Backport two patches to fix this. The first one is just a requirement for the later to apply. The second one is the real fix and it needed only a small adjustment to apply without backporing the commit 10887b59c7e7 ("fix --txstart-time report messages"). Fixes: 7d15f96eaf76 ("iperf: bump to 2.0.12") Signed-off-by: Rafał Miłecki (cherry picked from commit 87cd118794cc9375260ea213838e80ad5295e83c) --- package/network/utils/iperf/Makefile | 2 +- ...n-signal-handling-per-POSIX-calling-.patch | 43 +++++ ...rtup-fix-daemon-mode-per-redirecting.patch | 161 ++++++++++++++++++ 3 files changed, 205 insertions(+), 1 deletion(-) create mode 100644 package/network/utils/iperf/patches/0001-fix-latent-bug-in-signal-handling-per-POSIX-calling-.patch create mode 100644 package/network/utils/iperf/patches/0002-cleanup-main-startup-fix-daemon-mode-per-redirecting.patch diff --git a/package/network/utils/iperf/Makefile b/package/network/utils/iperf/Makefile index 3f7bfad9cc..6facf7bea7 100644 --- a/package/network/utils/iperf/Makefile +++ b/package/network/utils/iperf/Makefile @@ -9,7 +9,7 @@ include $(TOPDIR)/rules.mk PKG_NAME:=iperf PKG_VERSION:=2.0.12 -PKG_RELEASE:=1 +PKG_RELEASE:=2 PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz PKG_HASH:=367f651fb1264b13f6518e41b8a7e08ce3e41b2a1c80e99ff0347561eed32646 diff --git a/package/network/utils/iperf/patches/0001-fix-latent-bug-in-signal-handling-per-POSIX-calling-.patch b/package/network/utils/iperf/patches/0001-fix-latent-bug-in-signal-handling-per-POSIX-calling-.patch new file mode 100644 index 0000000000..a713e06b96 --- /dev/null +++ b/package/network/utils/iperf/patches/0001-fix-latent-bug-in-signal-handling-per-POSIX-calling-.patch @@ -0,0 +1,43 @@ +From 7c0ac64ebea38d0d9ff4d160db4d33bc087a3490 Mon Sep 17 00:00:00 2001 +From: Robert McMahon +Date: Mon, 16 Jul 2018 17:51:29 -0700 +Subject: [PATCH] fix latent bug in signal handling, per POSIX calling exit() + in signal handler is not safe. Use _exit() instead. Also, detect the user + signal SIGINT for the case of server needing two invocations to stop server + threads. Note: the server threads still need some work from graceful + termination with a single ctrl-c + +--- + +--- a/compat/signal.c ++++ b/compat/signal.c +@@ -171,7 +171,7 @@ void sig_exit( int inSigno ) { + static int num = 0; + if ( num++ == 0 ) { + fflush( 0 ); +- exit( 0 ); ++ _exit(0); + } + } /* end sig_exit */ + +--- a/src/main.cpp ++++ b/src/main.cpp +@@ -268,7 +268,7 @@ void Sig_Interupt( int inSigno ) { + // We try to not allow a single interrupt handled by multiple threads + // to completely kill the app so we save off the first thread ID + // then that is the only thread that can supply the next interrupt +- if ( thread_equalid( sThread, thread_zeroid() ) ) { ++ if ( (inSigno == SIGINT) && thread_equalid( sThread, thread_zeroid() ) ) { + sThread = thread_getid(); + } else if ( thread_equalid( sThread, thread_getid() ) ) { + sig_exit( inSigno ); +@@ -420,9 +420,3 @@ VOID ServiceStop() { + } + + #endif +- +- +- +- +- +- diff --git a/package/network/utils/iperf/patches/0002-cleanup-main-startup-fix-daemon-mode-per-redirecting.patch b/package/network/utils/iperf/patches/0002-cleanup-main-startup-fix-daemon-mode-per-redirecting.patch new file mode 100644 index 0000000000..c8655c9142 --- /dev/null +++ b/package/network/utils/iperf/patches/0002-cleanup-main-startup-fix-daemon-mode-per-redirecting.patch @@ -0,0 +1,161 @@ +From 755be8bdb48d2536e39d2d7cf84e8a8f86b8776f Mon Sep 17 00:00:00 2001 +From: Robert McMahon +Date: Sat, 6 Oct 2018 13:36:52 -0700 +Subject: [PATCH] cleanup main startup, fix daemon mode per redirecting stdin, + stderr and stdout to /dev/null + +--- + +--- a/src/main.cpp ++++ b/src/main.cpp +@@ -167,67 +167,7 @@ int main( int argc, char **argv ) { + Settings_ParseCommandLine( argc, argv, ext_gSettings ); + + // Check for either having specified client or server +- if ( ext_gSettings->mThreadMode == kMode_Client +- || ext_gSettings->mThreadMode == kMode_Listener ) { +-#ifdef WIN32 +- // Start the server as a daemon +- if ( isDaemon( ext_gSettings )) { +- if (ext_gSettings->mThreadMode == kMode_Listener) { +- CmdInstallService(argc, argv); +- } else { +- fprintf(stderr, "Client cannot be run as a daemon\n"); +- } +- return 0; +- } +- +- // Remove the Windows service if requested +- if ( isRemoveService( ext_gSettings ) ) { +- // remove the service +- if ( CmdRemoveService() ) { +- fprintf(stderr, "IPerf Service is removed.\n"); +- return 0; +- } +- } +-#else +- if ( isDaemon( ext_gSettings ) ) { +- if (ext_gSettings->mThreadMode != kMode_Listener) { +- fprintf(stderr, "Iperf client cannot be run as a daemon\n"); +- return 0; +- } +- if (daemon(1, 1) < 0) { +- perror("daemon"); +- } +- fprintf( stderr, "Running Iperf Server as a daemon\n"); +- fprintf( stderr, "The Iperf daemon process ID : %d\n",((int)getpid())); +- fclose(stdout); +- fclose(stderr); +- fclose(stdin); +- } +-#endif +- // initialize client(s) +- if ( ext_gSettings->mThreadMode == kMode_Client ) { +- client_init( ext_gSettings ); +- } +- +-#ifdef HAVE_THREAD +- // start up the reporter and client(s) or listener +- { +- thread_Settings *into = NULL; +- // Create the settings structure for the reporter thread +- Settings_Copy( ext_gSettings, &into ); +- into->mThreadMode = kMode_Reporter; +- +- // Have the reporter launch the client or listener +- into->runNow = ext_gSettings; +- +- // Start all the threads that are ready to go +- thread_start( into ); +- } +-#else +- // No need to make a reporter thread because we don't have threads +- thread_start( ext_gSettings ); +-#endif +- } else { ++ if ((ext_gSettings->mThreadMode != kMode_Client) && (ext_gSettings->mThreadMode != kMode_Listener)) { + // neither server nor client mode was specified + // print usage and exit + +@@ -236,20 +176,75 @@ int main( int argc, char **argv ) { + // Starting in 2.0 to restart a previously defined service + // you must call iperf with "iperf -D" or using the environment variable + SERVICE_TABLE_ENTRY dispatchTable[] = +- { +- { (LPSTR)TEXT(SZSERVICENAME), (LPSERVICE_MAIN_FUNCTION)service_main}, +- { NULL, NULL} +- }; ++ { ++ { (LPSTR)TEXT(SZSERVICENAME), (LPSERVICE_MAIN_FUNCTION)service_main}, ++ { NULL, NULL} ++ }; + + // starting the service by SCM, there is no arguments will be passed in. + // the arguments will pass into Service_Main entry. + if (!StartServiceCtrlDispatcher(dispatchTable) ) + // If the service failed to start then print usage + #endif +- fprintf( stderr, usage_short, argv[0], argv[0] ); ++ fprintf( stderr, usage_short, argv[0], argv[0] ); ++ return 0; ++ } ++ ++ ++ switch (ext_gSettings->mThreadMode) { ++ case kMode_Client : ++ if ( isDaemon( ext_gSettings ) ) { ++ fprintf(stderr, "Iperf client cannot be run as a daemon\n"); ++ return 0; ++ } ++ // initialize client(s) ++ client_init( ext_gSettings ); ++ break; ++ case kMode_Listener : ++ if ( isDaemon( ext_gSettings ) ) { ++ fprintf( stderr, "Running Iperf Server as a daemon\n"); ++ // Start the server as a daemon ++#ifdef WIN32 ++ CmdInstallService(argc, argv); ++ // Remove the Windows service if requested ++ if ( isRemoveService( ext_gSettings ) ) { ++ // remove the service ++ if ( CmdRemoveService() ) { ++ fprintf(stderr, "IPerf Service is removed.\n"); ++ return 0; ++ } ++ } ++#else ++ fflush(stderr); ++ // redirect stdin, stdout and sterr to /dev/null (see dameon and no close flag) ++ if (daemon(1, 0) < 0) { ++ perror("daemon"); ++ } ++ } ++#endif ++ break; ++ default : ++ fprintf( stderr, "unknown mode"); ++ break; ++ } ++#ifdef HAVE_THREAD ++ // start up the reporter and client(s) or listener ++ { ++ thread_Settings *into = NULL; ++ // Create the settings structure for the reporter thread ++ Settings_Copy( ext_gSettings, &into ); ++ into->mThreadMode = kMode_Reporter; ++ ++ // Have the reporter launch the client or listener ++ into->runNow = ext_gSettings; + +- return 0; ++ // Start all the threads that are ready to go ++ thread_start( into ); + } ++#else ++ // No need to make a reporter thread because we don't have threads ++ thread_start( ext_gSettings ); ++#endif + + // wait for other (client, server) threads to complete + thread_joinall(); -- 2.30.2