/* ------------------------------------------------------------------- *prototypes
* ------------------------------------------------------------------- */ // Function called at exit to clean up as much as possible void cleanup( void );
/* ------------------------------------------------------------------- *globalvariables
* ------------------------------------------------------------------- */ extern"C" { // Global flag to signal a user interrupt int sInterupted = 0; // Global ID that we increment to be used // as identifier for SUM reports int groupID = 0; // Mutex to protect access to the above ID
Mutex groupCond; // Condition used to signify advances of the current // records being accessed in a report and also to // serialize modification of the report list
Condition ReportCond;
Condition ReportDoneCond;
}
// global variables only accessed within this file
// Thread that received the SIGTERM or SIGINT signal // Used to ensure that if multiple threads receive the // signal we do not prematurely exit
nthread_t sThread; // The main thread uses this function to wait // for all other threads to complete void waitUntilQuit( void );
// Set SIGTERM and SIGINT to call our user interrupt function
my_signal( SIGTERM, Sig_Interupt );
my_signal( SIGINT, Sig_Interupt );
my_signal( SIGALRM, Sig_Interupt );
// Tell windows we want to handle our own signals
SetConsoleCtrlHandler( sig_dispatcher, true ); #endif
// Initialize global mutexes and conditions
Condition_Initialize ( &ReportCond );
Condition_Initialize ( &ReportDoneCond );
Mutex_Initialize( &groupCond );
Mutex_Initialize( &clients_mutex );
// Initialize the thread subsystem
thread_init( );
// Initialize the interrupt handling thread to 0
sThread = thread_zeroid();
// perform any cleanup when quitting Iperf
atexit( cleanup );
// Allocate the "global" settings
thread_Settings* ext_gSettings = new thread_Settings;
// Initialize settings to defaults
Settings_Initialize( ext_gSettings ); // read settings from environment variables
Settings_ParseEnvironment( ext_gSettings ); // read settings from command-line parameters
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 // Daemon mode for non-windows in handled // in the listener_spawn function if ( isDaemon( ext_gSettings ) ) {
CmdInstallService(argc, argv); return0;
}
// Remove the Windows service if requested if ( isRemoveService( ext_gSettings ) ) { // remove the service if ( CmdRemoveService() ) {
fprintf(stderr, "IPerf Service is removed.\n");
#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 { // neither server nor client mode was specified // print usage and exit
#ifdef WIN32 // In Win32 we also attempt to start a previously defined service // 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[] =
{
{ TEXT(SZSERVICENAME), (LPSERVICE_MAIN_FUNCTION)service_main},
{ NULL, NULL}
};
// Only attempt to start the service if "-D" was specified if ( !isDaemon(ext_gSettings) || // starting the service by SCM, there is no arguments will be passed in. // the arguments will pass into Service_Main entry.
!StartServiceCtrlDispatcher(dispatchTable) ) // If the service failed to start then print usage #endif
fprintf( stderr, usage_short, argv[0], argv[0] );
return0;
}
// wait for other (client, server) threads to complete
thread_joinall();
void Sig_Interupt( int inSigno ) { #ifdef HAVE_THREAD // 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() ) ) {
sThread = thread_getid();
} elseif ( thread_equalid( sThread, thread_getid() ) ) {
sig_exit( inSigno );
}
// global variable used by threads to see if they were interrupted
sInterupted = 1;
// with threads, stop waiting for non-terminating threads // (ie Listener Thread)
thread_release_nonterm( 1 );
#else // without threads, just exit quietly, same as sig_exit()
sig_exit( inSigno ); #endif
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.