diff --git a/CMakeLists.txt b/CMakeLists.txt index e1946b3e5..3690f499d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -175,6 +175,7 @@ add_option(OPTION_LIST ENABLE_UNIT_TESTS "Enable unit test of SDK." OFF) add_option(OPTION_LIST ENABLE_UPDATE_CHECK "Enable update check." ON) add_option(OPTION_LIST ENABLE_VIDEO "Enable Video support." YES) add_option(OPTION_LIST ENABLE_WINDOWS_TOOLS_CHECK "Enable tools checks on Windows for auto install." OFF) +add_option(OPTION_LIST ENABLE_CRASH_HANDLER "Enable Crash Handler" YES) add_cache(OPTION_LIST LINPHONE_SDK_MAKE_RELEASE_FILE_URL "Make a RELEASE file that work along check_version and use this URL" "") diff --git a/Linphone/CMakeLists.txt b/Linphone/CMakeLists.txt index 027e2d0bc..0b4fb7790 100644 --- a/Linphone/CMakeLists.txt +++ b/Linphone/CMakeLists.txt @@ -219,4 +219,102 @@ foreach(T ${QT_PACKAGES}) target_link_libraries(${TARGET_NAME} PRIVATE Qt6::${T}) endforeach() +################################################################ +# CRASHPAD +################################################################ +if (ENABLE_CRASH_HANDLER) + + # Clone required repos + ###################### + + function(clone_git_repo repo_url dest_dir) + if(NOT EXISTS ${dest_dir}) + execute_process( + COMMAND git clone ${repo_url} ${dest_dir} + RESULT_VARIABLE result + WORKING_DIRECTORY ${CMAKE_BINARY_DIR} + ) + if(result) + message(FATAL_ERROR "Failed to clone repository: ${repo_url}") + else() + message(STATUS "Repository cloned successfully: ${repo_url}") + endif() + else() + message(STATUS "Repository already cloned: ${dest_dir}") + endif() + endfunction() + + #clone_git_repo("https://gn.googlesource.com/gn" "${CMAKE_BINARY_DIR}/gn") + clone_git_repo("https://chromium.googlesource.com/chromium/tools/depot_tools.git" "${CMAKE_BINARY_DIR}/depot_tools") + #clone_git_repo("https://chromium.googlesource.com/crashpad/crashpad" "${CMAKE_BINARY_DIR}/crashpad") + + # Sync crashpad repo content with gclient + ########################################## + + execute_process( + COMMAND "${CMAKE_BINARY_DIR}/depot_tools/gclient" " config --name=crashpad" "--unmanaged" "https://chromium.googlesource.com/crashpad/crashpad" + #&& ${CMAKE_BINARY_DIR}/depot_tools/gclient sync + ENVIRONMENT "PATH=${CMAKE_BINARY_DIR}/depot_tools:$ENV{PATH}" + RESULT_VARIABLE result + OUTPUT_VARIABLE output + ERROR_VARIABLE error + WORKING_DIRECTORY ${CMAKE_BINARY_DIR} + ) + if(result) + message(FATAL_ERROR "Failed fetching craspad with gclient : ${result} ${output} ${error}") + endif() + + + # Build crashpad client + ########################################## + execute_process( + COMMAND gn gen -C out && ninja -C out + ENVIRONMENT "PATH=${CMAKE_BINARY_DIR}/depot_tools:$ENV{PATH}" + RESULT_VARIABLE result + WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/crashpad + ) + if(result) + message(FATAL_ERROR "Failed building crashpad") + endif() + + # Define Crashpad dependencies + ############################## + + set(CRASHPAD_LIB_DIR "${CMAKE_SOURCE_DIR}/external/crashpad/out/obj") + set(CRASHPAD_INCLUDE_DIR "${CMAKE_SOURCE_DIR}/external/crashpad") + + # Include Crashpad headers + ############################## + + target_include_directories(${TARGET_NAME} SYSTEM PRIVATE + ${CRASHPAD_INCLUDE_DIR} + ${CRASHPAD_INCLUDE_DIR}/third_party/mini_chromium/mini_chromium + ${CRASHPAD_INCLUDE_DIR}/out/gen + ) + + # Add Crashpad libraries + ############################## + + set(CRASHPAD_LIBRARIES + "${CRASHPAD_LIB_DIR}/client/libclient.a" + "${CRASHPAD_LIB_DIR}/util/libutil.a" + "${CRASHPAD_LIB_DIR}/third_party/mini_chromium/mini_chromium/base/libbase.a" + "${CRASHPAD_LIB_DIR}/util/libmig_output.a" + # Add more libraries here + ) + + foreach(lib_path ${CRASHPAD_LIBRARIES}) + # Create an imported target for each library + get_filename_component(lib_name ${lib_path} NAME_WE) # Get the base name of the file without extension + add_library(${lib_name} STATIC IMPORTED) + set_target_properties(${lib_name} PROPERTIES + IMPORTED_LOCATION ${lib_path} + ) + # Link it to your main target (replace YOUR_TARGET with your actual target name) + target_link_libraries(${TARGET_NAME} PRIVATE ${lib_name}) + endforeach() + + target_link_libraries(${TARGET_NAME} PRIVATE bsm) + +endif() diff --git a/Linphone/main.cpp b/Linphone/main.cpp index 92939ba45..5bf2c5524 100644 --- a/Linphone/main.cpp +++ b/Linphone/main.cpp @@ -22,12 +22,15 @@ FILE *gStream = NULL; #define ACCESSBILITY_WORKAROUND #include #include + void DummyUpdateHandler(QAccessibleEvent *event) { } void DummyRootObjectHandler(QObject *) { } #endif +#include + void cleanStream() { #ifdef _WIN32 if (gStream) { @@ -39,6 +42,28 @@ void cleanStream() { } int main(int argc, char *argv[]) { + + // Set up Crashpad + std::vector arguments; + + base::FilePath handler_path("/Users/Tof/Desktop/belledonne-communications/master-gitosis/linphone-desktop/external/" + "crashpad/out/crashpad_handler"); + base::FilePath database_path("crashes"); // TODO same place as logs. + base::FilePath metrics_path("metrics_path"); + + std::map annotations; + annotations["product"] = "Linphone"; // TODO from CMake + annotations["version"] = "1.0.0"; // TODO from CMAKE + + crashpad::CrashpadClient crashpad_client; + if (!crashpad_client.StartHandler(handler_path, database_path, metrics_path, + "https://files.linphone.org:443/http-file-transfer-server/hft.php", annotations, + arguments, true, true, {})) { + std::cerr << "Failed to start Crashpad handler. Crashes will not be logged." << std::endl; + } else { + std::cout << "Started Crashpad handler" << std::endl; + } + /* #if defined _WIN32 // log in console only if launched from console diff --git a/Linphone/model/setting/SettingsModel.cpp b/Linphone/model/setting/SettingsModel.cpp index 125cbc6cc..52cb16d99 100644 --- a/Linphone/model/setting/SettingsModel.cpp +++ b/Linphone/model/setting/SettingsModel.cpp @@ -55,6 +55,9 @@ SettingsModel::SettingsModel() { if (gstate == linphone::GlobalState::On) { // reached when misc|config-uri is set in config and app starts // and after config is fetched. notifyConfigReady(); + + int *p = nullptr; + *p = 42; // Causes segmentation fault } }); QObject::connect(CoreModel::getInstance().get(), &CoreModel::configuringStatus, this,