From bdbe2b36089f331c507dd2dee8d87078cd808636 Mon Sep 17 00:00:00 2001 From: Botond Baranyi <botond.baranyi@ericsson.com> Date: Wed, 18 Jan 2017 13:02:51 +0100 Subject: [PATCH] Fixed memory leaks in usage stats, JSON attribute parsing and ttcn2json (artf786863) Change-Id: I1ed85b104c3cbe89c3041a6c309867d353527228 Signed-off-by: Botond Baranyi <botond.baranyi@ericsson.com> --- common/usage_stats.cc | 20 ++++++-------- common/usage_stats.hh | 6 ++++- compiler2/main.cc | 24 +++++++++++++++-- compiler2/ttcn3/JsonAST.cc | 6 ++--- compiler2/ttcn3/JsonAST.hh | 6 ++--- compiler2/ttcn3/PatternString.cc | 4 ++- core/Module_list.cc | 26 +++++++++++++++---- core/Module_list.hh | 12 ++++++++- core/Runtime.cc | 12 ++++++++- .../XML/XmlWorkflow/src/xmlTest_Shell.ttcn | 5 ++++ regression_test/profiler/Shell.ttcn | 5 ++++ regression_test/ttcn2json/Shell.ttcn | 5 ++++ 12 files changed, 102 insertions(+), 29 deletions(-) diff --git a/common/usage_stats.cc b/common/usage_stats.cc index 4eb264a36..b268dfb15 100644 --- a/common/usage_stats.cc +++ b/common/usage_stats.cc @@ -194,32 +194,28 @@ UsageData::~UsageData() { } -struct thread_data { - std::string msg; - Sender* sndr; -}; -void UsageData::sendDataThreaded(std::string msg, Sender* sender) { - thread_data* data = new thread_data; // will be deleted by sendData - data->msg = "id="+ id + "&host=" + host + "&platform=" + platform + "&gccv=" + C_COMPILER_VERSION + "&titanv=" + PRODUCT_NUMBER + "&msg="+ msg + "\r"; - data->sndr = sender; +pthread_t UsageData::sendDataThreaded(std::string msg, thread_data* data) { + data->msg = "id="+ id + "&host=" + host + "&platform=" + platform + + "&gccv=" + C_COMPILER_VERSION + "&titanv=" + PRODUCT_NUMBER + "&msg="+ msg + "\r"; pthread_t thread; pthread_create(&thread, NULL, sendData, data); + return thread; } void* UsageData::sendData(void* m) { + // make sure the thread is cancelable if the main thread finishes first + pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL); + pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL); + thread_data* my_data; my_data = (thread_data*)m; if(my_data->sndr) { my_data->sndr->send(my_data->msg.c_str()); - delete my_data->sndr; } - // delete the data after use - delete my_data; - return NULL; } diff --git a/common/usage_stats.hh b/common/usage_stats.hh index 8c5af2ad7..b807f9ce1 100644 --- a/common/usage_stats.hh +++ b/common/usage_stats.hh @@ -61,6 +61,10 @@ public: void send(const char*); }; +struct thread_data { + std::string msg; + Sender* sndr; +}; class UsageData { public: @@ -69,7 +73,7 @@ public: static UsageData instance; // Guaranteed to be destroyed. return instance; // Instantiated on first use. } - static void sendDataThreaded(std::string msg, Sender* sender); + static pthread_t sendDataThreaded(std::string msg, thread_data* data); private: diff --git a/compiler2/main.cc b/compiler2/main.cc index 69275ce9a..f00d8ab44 100644 --- a/compiler2/main.cc +++ b/compiler2/main.cc @@ -1152,6 +1152,11 @@ int main(int argc, char *argv[]) unsigned int error_count = Error_Context::get_error_count(); if (error_count > 0) ret_val = EXIT_FAILURE; +#ifdef USAGE_STATS + pthread_t stats_thread = 0; + thread_data* stats_data = NULL; +#endif + if (parse_only || semantic_check_only) { // print detailed statistics Error_Context::print_error_statistics(); @@ -1184,8 +1189,9 @@ int main(int argc, char *argv[]) } } - HttpSender *sender = new HttpSender; - UsageData::getInstance().sendDataThreaded(stream.str(), sender); + stats_data = new thread_data; + stats_data->sndr = new HttpSender; + stats_thread = UsageData::getInstance().sendDataThreaded(stream.str(), stats_data); #endif if (ttcn2json) { NOTIFY("Generating JSON schema..."); @@ -1233,5 +1239,19 @@ int main(int argc, char *argv[]) // dbgnew.hh already does it: check_mem_leak(argv[0]); +#ifdef USAGE_STATS + if (stats_thread != 0) { + // cancel the usage stats thread if it hasn't finished yet + pthread_cancel(stats_thread); + pthread_join(stats_thread, NULL); + } + if (stats_data != NULL) { + if (stats_data->sndr != NULL) { + delete stats_data->sndr; + } + delete stats_data; + } +#endif + return ret_val; } diff --git a/compiler2/ttcn3/JsonAST.cc b/compiler2/ttcn3/JsonAST.cc index d23fb3c86..add80c0f6 100644 --- a/compiler2/ttcn3/JsonAST.cc +++ b/compiler2/ttcn3/JsonAST.cc @@ -15,10 +15,10 @@ #include <cstddef> #include <cstdio> -void JsonSchemaExtension::init(const char* p_key, const char* p_value) +void JsonSchemaExtension::init(char* p_key, char* p_value) { - key = mcopystr(p_key); - value = mcopystr(p_value); + key = p_key; + value = p_value; } JsonSchemaExtension::~JsonSchemaExtension() diff --git a/compiler2/ttcn3/JsonAST.hh b/compiler2/ttcn3/JsonAST.hh index e3519d499..3ac5b97ea 100644 --- a/compiler2/ttcn3/JsonAST.hh +++ b/compiler2/ttcn3/JsonAST.hh @@ -18,13 +18,13 @@ class JsonSchemaExtension { private: - void init(const char* p_key, const char* p_value); + void init(char* p_key, char* p_value); public: char* key; char* value; - JsonSchemaExtension(const char* p_key, const char* p_value) { init(p_key, p_value); } - JsonSchemaExtension(const JsonSchemaExtension& x) { init(x.key, x.value); } + JsonSchemaExtension(char* p_key, char* p_value) { init(p_key, p_value); } + JsonSchemaExtension(const JsonSchemaExtension& x) { init(mcopystr(x.key), mcopystr(x.value)); } ~JsonSchemaExtension(); }; diff --git a/compiler2/ttcn3/PatternString.cc b/compiler2/ttcn3/PatternString.cc index db00bc1e5..1e9daddbb 100644 --- a/compiler2/ttcn3/PatternString.cc +++ b/compiler2/ttcn3/PatternString.cc @@ -715,7 +715,9 @@ namespace Ttcn { regex_str = TTCN_pattern_to_regexp(utf8str.c_str(), true); } - return convert_to_json_string(regex_str); + char* json_str = convert_to_json_string(regex_str); + Free(regex_str); + return json_str; } } // namespace Ttcn diff --git a/core/Module_list.cc b/core/Module_list.cc index 5230a50ec..84b06f435 100644 --- a/core/Module_list.cc +++ b/core/Module_list.cc @@ -349,8 +349,9 @@ void Module_List::print_version() "--------------------\n", stderr); } -void Module_List::send_versions() { #ifdef USAGE_STATS +void Module_List::send_usage_stats(pthread_t& thread, thread_data*& data) +{ std::set<ModuleVersion> versions; for (TTCN_Module *list_iter = list_head; list_iter != NULL; list_iter = list_iter->list_next) { @@ -371,11 +372,26 @@ void Module_List::send_versions() { } } - HttpSender* sender = new HttpSender; - UsageData::getInstance().sendDataThreaded(stream.str().c_str(), sender); -#endif + data = new thread_data; + data->sndr = new HttpSender; + thread = UsageData::getInstance().sendDataThreaded(stream.str().c_str(), data); +} + +void Module_List::clean_up_usage_stats(pthread_t thread, thread_data* data) +{ + if (thread != 0) { + // cancel the usage stats thread if it hasn't finished yet + pthread_cancel(thread); + pthread_join(thread, NULL); + } + if (data != NULL) { + if (data->sndr != NULL) { + delete data->sndr; + } + delete data; + } } - +#endif // USAGE_STATS void Module_List::list_testcases() { diff --git a/core/Module_list.hh b/core/Module_list.hh index 93fee1c19..66fcc43d7 100644 --- a/core/Module_list.hh +++ b/core/Module_list.hh @@ -23,6 +23,9 @@ #include <stdio.h> #include "Types.h" +#ifdef USAGE_STATS +#include <pthread.h> +#endif class Text_Buf; class TTCN_Module; @@ -30,6 +33,9 @@ class Module_Param; class Module_Param_Name; class ModuleVersion; struct namespace_t; +#ifdef USAGE_STATS +struct thread_data; +#endif typedef void (*genericfunc_t)(void); @@ -64,7 +70,11 @@ public: static void execute_all_testcases(const char *module_name); static void print_version(); - static void send_versions(); + +#ifdef USAGE_STATS + static void send_usage_stats(pthread_t& thread, thread_data*& data); + static void clean_up_usage_stats(pthread_t thread, thread_data* data); +#endif static void list_testcases(); static void push_version(Text_Buf& text_buf); diff --git a/core/Runtime.cc b/core/Runtime.cc index 648ed6c37..7f94a74a4 100644 --- a/core/Runtime.cc +++ b/core/Runtime.cc @@ -447,12 +447,18 @@ int TTCN_Runtime::hc_main(const char *local_addr, const char *MC_addr, TTCN_Logger::log_HC_start(get_host_name()); TTCN_Logger::write_logger_settings(); TTCN_Snapshot::check_fd_setsize(); +#ifdef USAGE_STATS + pthread_t stats_thread = 0; + thread_data* stats_data = NULL; +#endif try { if (local_addr != NULL) TTCN_Communication::set_local_address(local_addr); TTCN_Communication::set_mc_address(MC_addr, MC_port); TTCN_Communication::connect_mc(); - Module_List::send_versions(); +#ifdef USAGE_STATS + Module_List::send_usage_stats(stats_thread, stats_data); +#endif executor_state = HC_IDLE; TTCN_Communication::send_version(); initialize_component_process_tables(); @@ -477,6 +483,10 @@ int TTCN_Runtime::hc_main(const char *local_addr, const char *MC_addr, TTCN_Logger::log_executor_runtime( API::ExecutorRuntime_reason::host__controller__finished); +#ifdef USAGE_STATS + Module_List::clean_up_usage_stats(stats_thread, stats_data); +#endif + return ret_val; } diff --git a/regression_test/XML/XmlWorkflow/src/xmlTest_Shell.ttcn b/regression_test/XML/XmlWorkflow/src/xmlTest_Shell.ttcn index cc91aeb47..2aca2d874 100644 --- a/regression_test/XML/XmlWorkflow/src/xmlTest_Shell.ttcn +++ b/regression_test/XML/XmlWorkflow/src/xmlTest_Shell.ttcn @@ -293,6 +293,11 @@ runs on Shell_CT pl_success:=false; } }//select + vl_pattern := "*(Memory leak at)*"; + if (regexp(v_ASP_PResult.stderr,vl_pattern,0) != "") { + log("Memory leak detected during command execution."); + pl_success := false; + } } else { log("The result code(", v_ASP_PResult.code, ") is not the expected(", vl_expectedCode, ")"); pl_success:=false; diff --git a/regression_test/profiler/Shell.ttcn b/regression_test/profiler/Shell.ttcn index c431eb9b4..8841e49fd 100644 --- a/regression_test/profiler/Shell.ttcn +++ b/regression_test/profiler/Shell.ttcn @@ -235,6 +235,11 @@ runs on Shell_CT pl_success:=false; } }//select + vl_pattern := "*(Memory leak at)*"; + if (regexp(v_ASP_PResult.stderr,vl_pattern,0) != "") { + log("Memory leak detected during command execution."); + pl_success := false; + } } else { log("The result code(", v_ASP_PResult.code, ") is not the expected(", vl_expectedCode, ")"); pl_success:=false; diff --git a/regression_test/ttcn2json/Shell.ttcn b/regression_test/ttcn2json/Shell.ttcn index 533beef6a..0b1899fa6 100644 --- a/regression_test/ttcn2json/Shell.ttcn +++ b/regression_test/ttcn2json/Shell.ttcn @@ -223,6 +223,11 @@ runs on Shell_CT pl_success:=false; } }//select + vl_pattern := "*(Memory leak at)*"; + if (regexp(v_ASP_PResult.stderr,vl_pattern,0) != "") { + log("Memory leak detected during command execution."); + pl_success := false; + } } else { log("The result code(", v_ASP_PResult.code, ") is not the expected(", vl_expectedCode, ")"); pl_success:=false; -- GitLab