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();