diff --git a/include/screen.hpp b/include/screen.hpp index 7d50b7649..7575c5b99 100644 --- a/include/screen.hpp +++ b/include/screen.hpp @@ -48,10 +48,10 @@ extern "C" { #define EXIT_BIND_ERROR -2 void screen_set_exename(char * exe_name); -void screen_init(void (*exit_handler)()); +void screen_init(); void screen_clear(); int screen_readkey(); -void screen_exit(int rc); -void screen_sigusr1(int /* not used */); +void screen_exit(); +void screen_show_errors(); #endif // __SCREEN_H__ diff --git a/include/sipp.hpp b/include/sipp.hpp index 7c4bd678b..a6ff8330a 100644 --- a/include/sipp.hpp +++ b/include/sipp.hpp @@ -288,6 +288,7 @@ extern bool twinSippMode _DEFVAL(false); extern bool extendedTwinSippMode _DEFVAL(false); extern bool nostdin _DEFVAL(false); +extern bool nostdout _DEFVAL(false); extern bool backgroundMode _DEFVAL(false); extern bool signalDump _DEFVAL(false); @@ -478,6 +479,8 @@ enum E_Alter_YesNo { #include "strings.hpp" +void sipp_exit(int rc); + char *get_peer_addr(char *); bool reconnect_allowed(); diff --git a/src/call.cpp b/src/call.cpp index 401cf4077..9e77fd958 100644 --- a/src/call.cpp +++ b/src/call.cpp @@ -3826,7 +3826,7 @@ call::T_ActionResult call::executeAction(char * msg, message *curmsg) quitting = 1; break; case CAction::E_INTCMD_STOP_NOW: - screen_exit(EXIT_TEST_RES_INTERNAL); + sipp_exit(EXIT_TEST_RES_INTERNAL); break; case CAction::E_INTCMD_STOPCALL: default: diff --git a/src/logger.cpp b/src/logger.cpp index 3a143d3ff..688636eb7 100644 --- a/src/logger.cpp +++ b/src/logger.cpp @@ -229,11 +229,11 @@ void print_statistics(int last) extern char *command_buffer; if(backgroundMode == false && display_scenario) { - if(!last) { + if (!nostdout && !last) { screen_clear(); } - if(first) { + if (!nostdout && first) { first = 0; printf("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n" "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"); diff --git a/src/screen.cpp b/src/screen.cpp index e940cc626..f0afbc964 100644 --- a/src/screen.cpp +++ b/src/screen.cpp @@ -47,8 +47,6 @@ int screen_inited = 0; char screen_exename[255]; extern bool backgroundMode; -void (*screen_exit_handler)(); - /* Clock must be a pointer to struct timeval */ #define GET_TIME(clock) \ { \ @@ -56,14 +54,6 @@ void (*screen_exit_handler)(); gettimeofday (clock, &tzp); \ } -void stop_all_traces() -{ - message_lfi.fptr = NULL; - log_lfi.fptr = NULL; - if(dumpInRtt) dumpInRtt = 0; - if(dumpInFile) dumpInFile = 0; -} - /* ERR is actually -1, but this prevents us from needing to use curses.h in * sipp.cpp. */ int screen_readkey() @@ -75,137 +65,32 @@ int screen_readkey() return c; } -void freeInFiles() -{ - for (file_map::iterator file_it = inFiles.begin(); file_it != inFiles.end(); file_it++) { - delete file_it->second; - } -} - -void freeUserVarMap() -{ - for (int_vt_map::iterator vt_it = userVarMap.begin(); vt_it != userVarMap.end(); vt_it++) { - vt_it->second->putTable(); - userVarMap[vt_it->first] = NULL; - } -} - -void releaseGlobalAllocations() -{ - delete main_scenario; - delete ooc_scenario; - delete aa_scenario; - free_default_messages(); - freeInFiles(); - freeUserVarMap(); - delete globalVariables; -} - -void screen_exit(int rc) +void screen_exit() { - unsigned long counter_value_failed=0; - unsigned long counter_value_success=0; - - /* Some signals may be delivered twice during exit() execution, - * and we must prevent all this from beeing done twice */ - - { - static int already_exited = 0; - if(already_exited) { - return; - } - already_exited = 1; - } - if( backgroundMode == false ) endwin(); +} - if(screen_exit_handler) { - screen_exit_handler(); - } - - if(screen_errors) { - fprintf(stderr, "%s", screen_last_error); - if(screen_errors > 1) { - if (screen_logfile[0] != (char)0) { - fprintf(stderr, - "%s: There were more errors, see '%s' file\n", - screen_exename, screen_logfile); - } else { - fprintf(stderr, - "%s: There were more errors, enable -trace_err to log them.\n", - screen_exename); - } - } - fflush(stderr); - } - - // Get failed calls counter value before releasing objects - if (display_scenario) { - counter_value_failed = display_scenario->stats->GetStat (CStat::CPT_C_FailedCall); - counter_value_success = display_scenario->stats->GetStat (CStat::CPT_C_SuccessfulCall); - } else { - rc = EXIT_TEST_FAILED; +void screen_show_errors() { + if (!screen_errors) { + return; } - releaseGlobalAllocations(); - - if (rc != EXIT_TEST_RES_UNKNOWN) { - // Exit is not a normal exit. Just use the passed exit code. - exit(rc); - } else { - // Normal exit: we need to determine if the calls were all - // successful or not. - // In order to compute the return code, get the counter - // of failed calls. If there is 0 failed calls, then everything is OK! - if (counter_value_failed == 0) { - - if ((timeout_exit) && (counter_value_success < 1)) { - - exit (EXIT_TEST_RES_INTERNAL); - } else { - exit(EXIT_TEST_OK); - } + fprintf(stderr, "%s", screen_last_error); + if (screen_errors > 1) { + if (screen_logfile[0] != '\0') { + fprintf(stderr, + "%s: There were more errors, see '%s' file\n", + screen_exename, screen_logfile); } else { - exit(EXIT_TEST_FAILED); + fprintf(stderr, + "%s: There were more errors, enable -trace_err to log them.\n", + screen_exename); } } + fflush(stderr); } -/* Exit handler for Curses */ - -void screen_quit() -{ - screen_exit(EXIT_TEST_RES_UNKNOWN); -} - - -void manage_oversized_file() -{ - FILE * f; - char L_file_name [MAX_PATH]; - struct timeval currentTime; - static int managing = 0; - - if(managing) return; //we can receive this signal more than once - - managing = 1; - - sprintf (L_file_name, "%s_%d_traces_oversized.log", scenario_file, getpid()); - f = fopen(L_file_name, "w"); - if(!f) ERROR_NO("Unable to open special error file\n"); - GET_TIME (¤tTime); - fprintf(f, - "-------------------------------------------- %s\n" - "Max file size reached - no more logs\n", - CStat::formatTime(¤tTime)); - fflush(f); - stop_all_traces(); - print_all_responses = 0; - error_lfi.fptr = NULL; -} - - void screen_clear() { printf("\033[2J"); @@ -216,38 +101,23 @@ void screen_set_exename(char * exe_name) strcpy(screen_exename, exe_name); } -void screen_init(void (*exit_handler)()) +void screen_init() { - struct sigaction action_quit, action_file_size_exceeded; - - screen_inited = 1; - screen_exit_handler = exit_handler; - - if (backgroundMode == false) { - /* Initializes curses and signals */ - initscr(); - /* Enhance performances and display */ - noecho(); + if (backgroundMode) { + return; } - /* Map exit handlers to curses reset procedure */ - memset(&action_quit, 0, sizeof(action_quit)); - memset(&action_file_size_exceeded, 0, sizeof(action_file_size_exceeded)); - (*(void **)(&(action_quit.sa_handler)))=(void *)screen_quit; - (*(void **)(&(action_file_size_exceeded.sa_handler)))=(void *)manage_oversized_file; - sigaction(SIGTERM, &action_quit, NULL); - sigaction(SIGINT, &action_quit, NULL); - sigaction(SIGXFSZ, &action_file_size_exceeded, NULL); // avoid core dump if the max file size is exceeded + screen_inited = 1; - if (backgroundMode == false) { - screen_clear(); - } + initscr(); + noecho(); + screen_clear(); } static void _screen_error(int fatal, bool use_errno, int error, const char *fmt, va_list ap) { static unsigned long long count = 0; - char * c = screen_last_error; + char *c = screen_last_error; struct timeval currentTime; CStat::globalStat(fatal ? CStat::E_FATAL_ERRORS : CStat::E_WARNING); @@ -262,12 +132,12 @@ static void _screen_error(int fatal, bool use_errno, int error, const char *fmt, c+= sprintf(c, ".\n"); screen_errors++; - if(screen_inited && !error_lfi.fptr && print_all_responses) { + if (!error_lfi.fptr && print_all_responses) { rotate_errorf(); - if(!error_lfi.fptr) { + if (screen_inited && !error_lfi.fptr) { sprintf(c, "%s: Unable to create '%s': %s.\n", screen_exename, screen_logfile, strerror(errno)); - screen_exit(EXIT_FATAL_ERROR); + sipp_exit(EXIT_FATAL_ERROR); } else { fprintf(error_lfi.fptr, "%s: The following events occured:\n", screen_exename); @@ -275,7 +145,7 @@ static void _screen_error(int fatal, bool use_errno, int error, const char *fmt, } } - if(error_lfi.fptr) { + if (error_lfi.fptr) { count += fprintf(error_lfi.fptr, "%s", screen_last_error); fflush(error_lfi.fptr); if (ringbuffer_size && count > ringbuffer_size) { @@ -296,18 +166,18 @@ static void _screen_error(int fatal, bool use_errno, int error, const char *fmt, fflush(stderr); } - if(fatal) { - if(!screen_inited) { - if(error == EADDRINUSE) { + if (fatal) { + if (!screen_inited) { + if (error == EADDRINUSE) { exit(EXIT_BIND_ERROR); } else { exit(EXIT_FATAL_ERROR); } } else { - if(error == EADDRINUSE) { - screen_exit(EXIT_BIND_ERROR); + if (error == EADDRINUSE) { + sipp_exit(EXIT_BIND_ERROR); } else { - screen_exit(EXIT_FATAL_ERROR); + sipp_exit(EXIT_FATAL_ERROR); } } } diff --git a/src/sipp.cpp b/src/sipp.cpp index 0e4ce4ea9..b3f925fd9 100644 --- a/src/sipp.cpp +++ b/src/sipp.cpp @@ -744,7 +744,7 @@ void traffic_thread() print_screens(); } - screen_exit(EXIT_TEST_RES_UNKNOWN); + sipp_exit(EXIT_TEST_RES_UNKNOWN); } } @@ -1129,6 +1129,139 @@ void print_last_stats() } } +void stop_all_traces() +{ + message_lfi.fptr = NULL; + log_lfi.fptr = NULL; + dumpInRtt = 0; + dumpInFile = 0; +} + +void freeInFiles() +{ + for (file_map::iterator file_it = inFiles.begin(); file_it != inFiles.end(); file_it++) { + delete file_it->second; + } +} + +void freeUserVarMap() +{ + for (int_vt_map::iterator vt_it = userVarMap.begin(); vt_it != userVarMap.end(); vt_it++) { + vt_it->second->putTable(); + userVarMap[vt_it->first] = NULL; + } +} + +void manage_oversized_file(int signum) +{ + FILE *f; + char L_file_name[MAX_PATH]; + struct timeval currentTime; + static int managing = 0; + + // we can receive this signal more than once + if (managing) { + return; + } + managing = 1; + + snprintf(L_file_name, MAX_PATH, "%s_%d_traces_oversized.log", scenario_file, getpid()); + f = fopen(L_file_name, "w"); + if (!f) { + ERROR_NO("Unable to open oversized log file\n"); + } + + GET_TIME(¤tTime); + fprintf(f, + "-------------------------------------------- %s\n" + "Max file size reached - no more logs\n", + CStat::formatTime(¤tTime)); + + fflush(f); + stop_all_traces(); + print_all_responses = 0; + error_lfi.fptr = NULL; +} + +void releaseGlobalAllocations() +{ + delete main_scenario; + delete ooc_scenario; + delete aa_scenario; + free_default_messages(); + freeInFiles(); + freeUserVarMap(); + delete globalVariables; +} + +void sipp_exit(int rc) +{ + unsigned long counter_value_failed = 0; + unsigned long counter_value_success = 0; + + /* Some signals may be delivered twice during exit() execution, + and we must prevent all this from beeing done twice */ + + { + static int already_exited = 0; + if (already_exited) { + return; + } + already_exited = 1; + } + + screen_exit(); + print_last_stats(); + screen_show_errors(); + + // Get failed calls counter value before releasing objects + if (display_scenario) { + counter_value_failed = display_scenario->stats->GetStat(CStat::CPT_C_FailedCall); + counter_value_success = display_scenario->stats->GetStat(CStat::CPT_C_SuccessfulCall); + } else { + rc = EXIT_TEST_FAILED; + } + + releaseGlobalAllocations(); + + if (rc != EXIT_TEST_RES_UNKNOWN) { + // Exit is not a normal exit. Just use the passed exit code. + exit(rc); + } else { + // Normal exit: we need to determine if the calls were all + // successful or not. In order to compute the return code, get + // the counter of failed calls. If there is 0 failed calls, + // then everything is OK! + if (counter_value_failed == 0) { + if (timeout_exit && counter_value_success < 1) { + exit(EXIT_TEST_RES_INTERNAL); + } else { + exit(EXIT_TEST_OK); + } + } else { + exit(EXIT_TEST_FAILED); + } + } +} + +static void sipp_sighandler(int signum) +{ + sipp_exit(EXIT_TEST_RES_UNKNOWN); +} + +static void sighandle_set() +{ + struct sigaction action_quit = {}; + struct sigaction action_file_size_exceeded = {}; + + action_quit.sa_handler = sipp_sighandler; + action_file_size_exceeded.sa_handler = manage_oversized_file; + + sigaction(SIGTERM, &action_quit, NULL); + sigaction(SIGINT, &action_quit, NULL); + sigaction(SIGXFSZ, &action_file_size_exceeded, NULL); // avoid core dump if the max file size is exceeded +} + char* remove_pattern(char* P_buffer, char* P_extensionPattern) { @@ -1906,7 +2039,13 @@ int main(int argc, char *argv[]) ERROR("SIPp cannot use out-of-call scenarios when running in server mode"); } - screen_init(print_last_stats); + if (!isatty(fileno(stdout))) + nostdout = true; + + if (!nostdout) + screen_init(); + + sighandle_set(); /* checking if we need to launch the tool in background mode */ if(backgroundMode == true) {