diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 3d96ab2..b09942b 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -5,6 +5,7 @@ variables: INSTALL_PREFIX: "/home/tsg/tfe" FRAMEWORK_REPO_ID: mesa-framework-stable UPLOAD_TO_REPO_ID: mesa-framework-testing + UPLOAD_SYMBOL_FILES: 0 TESTING_VERSION_BUILD: 0 stages: @@ -53,6 +54,7 @@ testing_version_build_debug: extends: .build_by_travis variables: TESTING_VERSION_BUILD: 1 + UPLOAD_SYMBOL_FILES: 1 BUILD_TYPE: Debug PACKAGE: 1 only: @@ -64,6 +66,7 @@ testing_version_build_release: extends: .build_by_travis variables: TESTING_VERSION_BUILD: 1 + UPLOAD_SYMBOL_FILES: 1 BUILD_TYPE: RelWithDebInfo PACKAGE: 1 only: @@ -74,6 +77,7 @@ product_build_debug: stage: build variables: UPLOAD_TO_REPO_ID: mesa-framework-stable + UPLOAD_SYMBOL_FILES: 1 BUILD_TYPE: Debug PACKAGE: 1 extends: .build_by_travis @@ -89,6 +93,7 @@ product_build_release: variables: UPLOAD_TO_REPO_ID: mesa-framework-stable BUILD_TYPE: RelWithDebInfo + UPLOAD_SYMBOL_FILES: 1 PACKAGE: 1 extends: .build_by_travis artifacts: diff --git a/ci/travis.sh b/ci/travis.sh index 28c1035..bef200a 100644 --- a/ci/travis.sh +++ b/ci/travis.sh @@ -49,3 +49,8 @@ if [ -n "${PACKAGE}" ]; then pulp-admin rpm repo uploads rpm --repo-id ${UPLOAD_TO_REPO_ID} -d ./ pulp-admin rpm repo publish run --repo-id ${UPLOAD_TO_REPO_ID} fi + +if [ -n "${UPLOAD_SYMBOL_FILES}" ]; then + sentry-cli login + sentry-cli upload-dif -t elf build/ +fi diff --git a/platform/src/proxy.cpp b/platform/src/proxy.cpp index 32f010d..74ddd43 100644 --- a/platform/src/proxy.cpp +++ b/platform/src/proxy.cpp @@ -16,6 +16,7 @@ #include #include #include +#include #include #include @@ -392,16 +393,65 @@ struct breakpad_instance /* 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]; + + /* Upload tools name */ + char upload_tools_filename[TFE_STRING_MAX]; + + /* Upload tools exec command */ + char * upload_tools_exec_argv[64]; + char * minidump_filename; }; -static bool tfe_breakpad_dump_callback(const google_breakpad::MinidumpDescriptor& descriptor, +static bool tfe_breakpad_dump_to_file(const google_breakpad::MinidumpDescriptor& descriptor, void* context, bool succeeded) { fprintf(stderr, "Crash happened, minidump path: %s\n", descriptor.path()); return succeeded; } +static bool tfe_breakpad_dump_and_report(const google_breakpad::MinidumpDescriptor& descriptor, + void* context, bool succeeded) +{ + struct breakpad_instance * instance = g_default_proxy->breakpad; + int ret = 0; + + strncpy(instance->minidump_filename, descriptor.path(), PATH_MAX - 1); + fprintf(stderr, "Crash happened, prepare upload the minidump file: %s\n", descriptor.path()); + + ret = access(instance->minidump_filename, F_OK | R_OK); + if (ret < 0) + { + fprintf(stderr, "minidump file is not existed, cannot upload minidump file"); + return succeeded; + } + + /* Firstly, fork an child process */ + pid_t exec_child_pid = fork(); + if (exec_child_pid == 0) + { + /* As a child, exec minidump upload tools */ + ret = execv(instance->upload_tools_filename, instance->upload_tools_exec_argv); + if (ret < 0) + { + fprintf(stderr, "Failed at exec the upload program %s: %s\n", + instance->upload_tools_filename, strerror(errno)); + } + + exit(EXIT_FAILURE); + } + else if (exec_child_pid > 0) + { + fprintf(stderr, "Starting upload minidump, PID = %d. \n", exec_child_pid); + return succeeded; + } + else + { + /* failed at fork, cannot upload the minidump */ + fprintf(stderr, "Failed at fork(), cannot upload minidump file. : %s\n", strerror(errno)); + return succeeded; + } +} + /* COREDUMP GENERATE TEST */ static void segv_generate() { @@ -431,6 +481,55 @@ static void _mkdir(const char *dir) mkdir(tmp, S_IRWXU); } +int breakpad_init_minidump_upload(struct breakpad_instance * instance, const char * profile) +{ + int ret = 0; + char execpath[PATH_MAX] = {}; + char * execdirname = NULL; + + 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 = readlink("/proc/self/exe", execpath, sizeof(execpath)); + if(unlikely(ret < 0)) + { + TFE_LOG_ERROR(g_default_logger, "Failed at readlink /proc/self/exec: %s", strerror(errno)); + goto errout; + } + + execdirname = dirname(execpath); + snprintf(instance->upload_tools_filename, sizeof(instance->upload_tools_filename) - 1, + "%s/%s", execdirname, "minidump_upload"); + + + /* Execfile */ + instance->upload_tools_exec_argv[0] = tfe_strdup(instance->upload_tools_filename); + + /* Firstly, Product Name and Product Version */ + instance->upload_tools_exec_argv[1] = tfe_strdup("-p"); + instance->upload_tools_exec_argv[2] = tfe_strdup("tfe"); + instance->upload_tools_exec_argv[3] = tfe_strdup("-v"); + instance->upload_tools_exec_argv[4] = tfe_strdup(tfe_version()); + + /* Minidump file location, now we don't know it */ + instance->minidump_filename = (char *)ALLOC(char, PATH_MAX); + instance->upload_tools_exec_argv[5] = instance->minidump_filename; + + /* Minidup upload url */ + instance->upload_tools_exec_argv[6] = tfe_strdup(instance->minidump_sentry_upload_url); + instance->upload_tools_exec_argv[7] = NULL; + return 0; + +errout: + return -1; +} + struct breakpad_instance * breakpad_init(const char * profile) { struct breakpad_instance * instance = ALLOC(struct breakpad_instance, 1); @@ -450,41 +549,36 @@ struct breakpad_instance * breakpad_init(const char * profile) 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); + if (instance->en_breakpad_upload) + { + /* Try to init the breakpad upload */ + ret = breakpad_init_minidump_upload(instance, profile); + if (ret < 0) + { + TFE_LOG_ERROR(g_default_logger, "Breakpad upload init failed, using local breakpad dumpfile"); + instance->en_breakpad_upload = 0; + } + } + + if (instance->en_breakpad_upload) + { + instance->exceptionHandler = new google_breakpad::ExceptionHandler( + google_breakpad::MinidumpDescriptor(instance->minidump_dir_prefix), NULL, + tfe_breakpad_dump_and_report, NULL, true, -1); + } + else + { + instance->exceptionHandler = new google_breakpad::ExceptionHandler( + google_breakpad::MinidumpDescriptor(instance->minidump_dir_prefix), NULL, + tfe_breakpad_dump_to_file, 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[]) diff --git a/vendor/CMakeLists.txt b/vendor/CMakeLists.txt index 109b588..aa0b2f2 100644 --- a/vendor/CMakeLists.txt +++ b/vendor/CMakeLists.txt @@ -348,3 +348,9 @@ 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) + +# install the minidump tools to target binary dir +install(PROGRAMS ${INSTALL_DIR}/bin/minidump-2-core DESTINATION bin COMPONENT Program) +install(PROGRAMS ${INSTALL_DIR}/bin/minidump_dump DESTINATION bin COMPONENT Program) +install(PROGRAMS ${INSTALL_DIR}/bin/minidump_stackwalk DESTINATION bin COMPONENT Program) +install(PROGRAMS ${INSTALL_DIR}/bin/minidump_upload DESTINATION bin COMPONENT Program)