diff --git a/platform/CMakeLists.txt b/platform/CMakeLists.txt index 871bdb1..42ca6eb 100644 --- a/platform/CMakeLists.txt +++ b/platform/CMakeLists.txt @@ -13,14 +13,15 @@ target_link_libraries(tfe pthread dl libevent-static libevent-static-openssl libevent-static-pthreads -# gperftools-static MESA_handle_logger MESA_prof_load cjson libcurl-static hiredis-static MESA_htable wiredcfg - MESA_field_stat) + MESA_field_stat + gperftools-static + breakpad-client-static) if(ENABLE_PLUGIN_HTTP) target_link_libraries(tfe -Wl,--whole-archive http -Wl,--no-whole-archive) diff --git a/platform/include/internal/proxy.h b/platform/include/internal/proxy.h index d3dee51..7ce9d79 100644 --- a/platform/include/internal/proxy.h +++ b/platform/include/internal/proxy.h @@ -9,6 +9,7 @@ struct ssl_mgr; struct key_keeper; struct acceptor_kni_v2; struct watchdog_kni; +struct breakpad_instance; enum TFE_STAT_FIELD { @@ -121,6 +122,9 @@ struct tfe_proxy /* PERFOMANCE MONIOTR VARIABLES*/ long long stat_val[TFE_STAT_MAX]; int fs_id[TFE_STAT_MAX]; + + /* Crash Report */ + struct breakpad_instance * breakpad; }; extern struct tfe_proxy * g_default_proxy; diff --git a/platform/src/proxy.cpp b/platform/src/proxy.cpp index 0406ed6..eca3270 100644 --- a/platform/src/proxy.cpp +++ b/platform/src/proxy.cpp @@ -7,6 +7,7 @@ #include #include #include +#include #include #include #include @@ -43,6 +44,11 @@ #include #include +/* Breakpad */ +#include +#include + + extern struct ssl_policy_enforcer* ssl_policy_enforcer_create(void* logger); extern enum ssl_stream_action ssl_policy_enforce(struct ssl_stream *upstream, void* u_para); @@ -377,6 +383,110 @@ void tfe_proxy_acceptor_init(struct tfe_proxy * proxy, const char * profile) return; } +struct breakpad_instance +{ + unsigned int en_breakpad; + char minidump_dir_prefix[TFE_STRING_MAX]; + google_breakpad::ExceptionHandler * exceptionHandler; + + /* Upload to crash server */ + unsigned int en_breakpad_upload; + char minidump_sentry_upload_url[TFE_STRING_MAX]; + char minidump_sentry_upload_token[TFE_STRING_MAX]; +}; + +static bool tfe_breakpad_dump_callback(const google_breakpad::MinidumpDescriptor& descriptor, + void* context, bool succeeded) +{ + fprintf(stderr, "Crash happened, minidump path: %s\n", descriptor.path()); + return succeeded; +} + +/* COREDUMP GENERATE TEST */ +static void segv_generate() +{ + char * _NULLPTR = NULL; + (*_NULLPTR) = 0; +} + +static void _mkdir(const char *dir) +{ + char tmp[PATH_MAX]; + char * p = NULL; + size_t len; + + snprintf(tmp, sizeof(tmp), "%s", dir); + len = strlen(tmp); + if (tmp[len - 1] == '/') + tmp[len - 1] = 0; + for (p = tmp + 1; *p; p++) + { + if (*p == '/') + { + *p = 0; + mkdir(tmp, S_IRWXU); + *p = '/'; + } + } + mkdir(tmp, S_IRWXU); +} + +struct breakpad_instance * breakpad_init(const char * profile) +{ + struct breakpad_instance * instance = ALLOC(struct breakpad_instance, 1); + assert(instance != nullptr); + + int ret = 0; + MESA_load_profile_uint_def(profile, "system", "enable_breakpad", &instance->en_breakpad, 1); + if (instance->en_breakpad <= 0) + { + TFE_LOG_ERROR(g_default_logger, "Breakpad Crash Reporting System is disabled. "); + return instance; + } + + MESA_load_profile_string_def(profile, "system", "breakpad_minidump_dir", + instance->minidump_dir_prefix, sizeof(instance->minidump_dir_prefix), "/tmp/crashreport"); + + MESA_load_profile_uint_def(profile, "system", "enable_breakpad_upload", + &instance->en_breakpad_upload, 0); + + if (instance->en_breakpad_upload) + { + ret = MESA_load_profile_string_nodef(profile, "system", "breakpad_upload_url", + instance->minidump_sentry_upload_url, sizeof(instance->minidump_sentry_upload_url)); + + if (unlikely(ret < 0)) + { + TFE_LOG_ERROR(g_default_logger, "breakpad_upload_url is necessary, failed. "); + goto errout; + } + + ret = MESA_load_profile_string_nodef(profile, "system", "breakpad_upload_token", + instance->minidump_sentry_upload_token, sizeof(instance->minidump_sentry_upload_token)); + + if (unlikely(ret < 0)) + { + TFE_LOG_ERROR(g_default_logger, "breakpad_upload_token is necessary, failed. "); + goto errout; + } + } + + /* Create the minidump dir if it is not existed */ + _mkdir(instance->minidump_dir_prefix); + + instance->exceptionHandler = new google_breakpad::ExceptionHandler( + google_breakpad::MinidumpDescriptor(instance->minidump_dir_prefix), NULL, + tfe_breakpad_dump_callback, NULL,true, -1); + + TFE_LOG_INFO(g_default_logger, "Breakpad Crash Report is enable. "); + TFE_LOG_INFO(g_default_logger, "Minidump Dir: %s", instance->minidump_dir_prefix); + return instance; + +errout: + if (instance) free(instance); + return NULL; +} + int main(int argc, char * argv[]) { const char * main_profile = "./conf/tfe/tfe.conf"; @@ -398,7 +508,6 @@ int main(int argc, char * argv[]) /* adds locking, only required if accessed from separate threads */ evthread_use_pthreads(); - unsigned int __log_level = RLOG_LV_INFO; MESA_load_profile_uint_def(main_profile, "log", "level", &__log_level, RLOG_LV_INFO); @@ -412,14 +521,17 @@ int main(int argc, char * argv[]) exit(EXIT_FAILURE); } - future_promise_library_init(future_profile); - tango_cache_global_init(); - /* PROXY INSTANCE */ g_default_proxy = ALLOC(struct tfe_proxy, 1); assert(g_default_proxy); strcpy(g_default_proxy->name, "tfe3a"); + g_default_proxy->breakpad = breakpad_init(main_profile); + CHECK_OR_EXIT(g_default_proxy->breakpad, "Failed at starting breakpad. Exit."); + + future_promise_library_init(future_profile); + tango_cache_global_init(); + /* CONFIG */ ret = tfe_proxy_config(g_default_proxy, main_profile); CHECK_OR_EXIT(ret == 0, "Failed at loading profile %s, Exit.", main_profile); @@ -482,7 +594,6 @@ int main(int argc, char * argv[]) TFE_LOG_ERROR(g_default_logger, "Tango Frontend Engine initialized. "); event_base_dispatch(g_default_proxy->evbase); - return 0; } diff --git a/vendor/CMakeLists.txt b/vendor/CMakeLists.txt index cac4b79..621d084 100644 --- a/vendor/CMakeLists.txt +++ b/vendor/CMakeLists.txt @@ -330,3 +330,21 @@ add_library(gperftools-static STATIC IMPORTED GLOBAL) add_dependencies(gperftools-static gperftools) set_property(TARGET gperftools-static PROPERTY IMPORTED_LOCATION ${INSTALL_DIR}/lib/libtcmalloc.a) set_property(TARGET gperftools-static PROPERTY INTERFACE_INCLUDE_DIRECTORIES ${INSTALL_DIR}/include) + +### Google Breakpad Binary +### Caution: This package is a pre-compiled binary package, only used in x86_64 servers. +ExternalProject_Add(breakpad + PREFIX breakpad + URL ${CMAKE_CURRENT_SOURCE_DIR}/breakpad-master-abfe08e.tar.gz + URL_MD5 96fb25a9d96cc55db71a7f374ad363b4 + CONFIGURE_COMMAND ./configure --prefix= + BUILD_IN_SOURCE 1) + +ExternalProject_Get_Property(breakpad INSTALL_DIR) +file(MAKE_DIRECTORY ${INSTALL_DIR}/include/breakpad) + +add_library(breakpad-client-static STATIC IMPORTED GLOBAL) +add_dependencies(breakpad-client-static breakpad) +set_property(TARGET breakpad-client-static PROPERTY IMPORTED_LOCATION ${INSTALL_DIR}/lib/libbreakpad_client.a) +set_property(TARGET breakpad-client-static PROPERTY INTERFACE_INCLUDE_DIRECTORIES ${INSTALL_DIR}/include/breakpad) +target_link_libraries(breakpad-client-static INTERFACE pthread) diff --git a/vendor/breakpad-master-abfe08e.tar.gz b/vendor/breakpad-master-abfe08e.tar.gz new file mode 100644 index 0000000..fd75aad Binary files /dev/null and b/vendor/breakpad-master-abfe08e.tar.gz differ