mirror of
https://github.com/cookiengineer/audacity
synced 2025-04-30 07:39:42 +02:00
💩 Remove Breakpad Crash Reports
This commit is contained in:
parent
5728dd542f
commit
2a37cd19a0
2
.github/workflows/cmake_build.yml
vendored
2
.github/workflows/cmake_build.yml
vendored
@ -80,8 +80,6 @@ jobs:
|
|||||||
|
|
||||||
- name: Configure
|
- name: Configure
|
||||||
env:
|
env:
|
||||||
# Error reporing
|
|
||||||
CRASH_REPORT_URL: ${{ secrets.CRASH_REPORT_URL }}
|
|
||||||
# Apple code signing
|
# Apple code signing
|
||||||
APPLE_CODESIGN_IDENTITY: ${{ secrets.APPLE_CODESIGN_IDENTITY }}
|
APPLE_CODESIGN_IDENTITY: ${{ secrets.APPLE_CODESIGN_IDENTITY }}
|
||||||
APPLE_NOTARIZATION_USER_NAME: ${{ secrets.APPLE_NOTARIZATION_USER_NAME }}
|
APPLE_NOTARIZATION_USER_NAME: ${{ secrets.APPLE_NOTARIZATION_USER_NAME }}
|
||||||
|
@ -204,10 +204,6 @@ elseif( CMAKE_SYSTEM_NAME MATCHES "Darwin" )
|
|||||||
message( STATUS " MacOS SDK: ${CMAKE_OSX_SYSROOT}" )
|
message( STATUS " MacOS SDK: ${CMAKE_OSX_SYSROOT}" )
|
||||||
message( STATUS )
|
message( STATUS )
|
||||||
|
|
||||||
if(${_OPT}has_crashreports)
|
|
||||||
set(CMAKE_XCODE_ATTRIBUTE_DEBUG_INFORMATION_FORMAT "dwarf-with-dsym")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# Try to get the current commit information
|
# Try to get the current commit information
|
||||||
@ -476,9 +472,6 @@ add_subdirectory( "cmake-proxies" )
|
|||||||
resolve_conan_dependencies()
|
resolve_conan_dependencies()
|
||||||
|
|
||||||
add_subdirectory( "help" )
|
add_subdirectory( "help" )
|
||||||
if(${_OPT}has_crashreports)
|
|
||||||
add_subdirectory( "crashreports" )
|
|
||||||
endif()
|
|
||||||
add_subdirectory( "images" )
|
add_subdirectory( "images" )
|
||||||
add_subdirectory( "libraries" )
|
add_subdirectory( "libraries" )
|
||||||
add_subdirectory( "locale" )
|
add_subdirectory( "locale" )
|
||||||
|
@ -18,10 +18,6 @@ add_conan_lib(
|
|||||||
expat:shared=True
|
expat:shared=True
|
||||||
)
|
)
|
||||||
|
|
||||||
if(${_OPT}has_crashreports)
|
|
||||||
add_conan_lib(breakpad breakpad/0.1 REQUIRED)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
set( wx_zlib "zlib" )
|
set( wx_zlib "zlib" )
|
||||||
|
|
||||||
set( wx_png "libpng" )
|
set( wx_png "libpng" )
|
||||||
|
@ -1,51 +0,0 @@
|
|||||||
/*!********************************************************************
|
|
||||||
*
|
|
||||||
Audacity: A Digital Audio Editor
|
|
||||||
|
|
||||||
BreakpadConfigurer.cpp
|
|
||||||
|
|
||||||
Vitaly Sverchinsky
|
|
||||||
|
|
||||||
**********************************************************************/
|
|
||||||
|
|
||||||
#include "BreakpadConfigurer.h"
|
|
||||||
|
|
||||||
#if defined(WIN32)
|
|
||||||
#include "internal/win32/CrashReportContext.h"
|
|
||||||
#else
|
|
||||||
#include "internal/unix/CrashReportContext.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
BreakpadConfigurer& BreakpadConfigurer::SetDatabasePathUTF8(const std::string& pathUTF8)
|
|
||||||
{
|
|
||||||
mDatabasePathUTF8 = pathUTF8;
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
BreakpadConfigurer& BreakpadConfigurer::SetReportURL(const std::string& reportURL)
|
|
||||||
{
|
|
||||||
mReportURL = reportURL;
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
BreakpadConfigurer& BreakpadConfigurer::SetParameters(const std::map<std::string, std::string>& parameters)
|
|
||||||
{
|
|
||||||
mParameters = parameters;
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
BreakpadConfigurer& BreakpadConfigurer::SetSenderPathUTF8(const std::string& pathUTF8)
|
|
||||||
{
|
|
||||||
mSenderPathUTF8 = pathUTF8;
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
void BreakpadConfigurer::Start()
|
|
||||||
{
|
|
||||||
static CrashReportContext context{};
|
|
||||||
bool ok = context.SetSenderPathUTF8(mSenderPathUTF8);
|
|
||||||
ok = ok && context.SetReportURL(mReportURL);
|
|
||||||
ok = ok && context.SetParameters(mParameters);
|
|
||||||
if (ok)
|
|
||||||
context.StartHandler(mDatabasePathUTF8);
|
|
||||||
}
|
|
@ -1,45 +0,0 @@
|
|||||||
/*!********************************************************************
|
|
||||||
*
|
|
||||||
Audacity: A Digital Audio Editor
|
|
||||||
|
|
||||||
BreakpadConfigurer.h
|
|
||||||
|
|
||||||
Vitaly Sverchinsky
|
|
||||||
|
|
||||||
**********************************************************************/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <string>
|
|
||||||
#include <map>
|
|
||||||
|
|
||||||
//! This class is used to configure Breakpad's handler before start.
|
|
||||||
/*! Typically handler should be started as early as possible.
|
|
||||||
* BreakpadConfigurer may be a short living object, it is used to configure
|
|
||||||
* Breakpad handler, and run it with BreakpadConfigurer::Start() method,
|
|
||||||
* It's expected that Start() will be called once during application
|
|
||||||
* lifetime, any calls to Set* methods after handler is started will be ignored.
|
|
||||||
* The handler itself simply starts crash sender program, passing all the details
|
|
||||||
* (path crash dump, report url, parameters...) as a command-line arguments to it.
|
|
||||||
* Please read official documentation for details:
|
|
||||||
* https://chromium.googlesource.com/breakpad/breakpad
|
|
||||||
*/
|
|
||||||
class BreakpadConfigurer final
|
|
||||||
{
|
|
||||||
std::string mDatabasePathUTF8;
|
|
||||||
std::string mSenderPathUTF8;
|
|
||||||
std::string mReportURL;
|
|
||||||
std::map<std::string, std::string> mParameters;
|
|
||||||
public:
|
|
||||||
//! Sets the directory where crashreports will be stored (should have rw permission)
|
|
||||||
BreakpadConfigurer& SetDatabasePathUTF8(const std::string& pathUTF8);
|
|
||||||
//! Sets report URL to the crash reporting server (URL-Encoded, optional)
|
|
||||||
BreakpadConfigurer& SetReportURL(const std::string& reportURL);
|
|
||||||
//! Sets an additional parameters that should be sent to a crash reporting server (ASCII encoded)
|
|
||||||
BreakpadConfigurer& SetParameters(const std::map<std::string, std::string>& parameters);
|
|
||||||
//! Sets a path to a directory where crash reporter sending program is located
|
|
||||||
BreakpadConfigurer& SetSenderPathUTF8(const std::string& pathUTF8);
|
|
||||||
|
|
||||||
//! Starts the handler
|
|
||||||
void Start();
|
|
||||||
};
|
|
@ -1,53 +0,0 @@
|
|||||||
# This module provides an interface to configure and start Breakpad handler
|
|
||||||
# in a platform independent way.
|
|
||||||
|
|
||||||
set(TARGET crashreports)
|
|
||||||
set(TARGET_ROOT ${CMAKE_CURRENT_SOURCE_DIR})
|
|
||||||
|
|
||||||
message( STATUS "========== Configuring ${TARGET} ==========" )
|
|
||||||
|
|
||||||
add_library(${TARGET} STATIC)
|
|
||||||
|
|
||||||
set(SOURCES "")
|
|
||||||
set(INCLUDES INTERFACE ./)
|
|
||||||
set(LIBRARIES "")
|
|
||||||
set(DEFINIES "")
|
|
||||||
|
|
||||||
# also adding Crash Reporting dialog
|
|
||||||
add_subdirectory(crashreporter)
|
|
||||||
|
|
||||||
list(APPEND SOURCES
|
|
||||||
PRIVATE
|
|
||||||
BreakpadConfigurer.h
|
|
||||||
BreakpadConfigurer.cpp
|
|
||||||
)
|
|
||||||
list(APPEND LIBRARIES
|
|
||||||
PRIVATE
|
|
||||||
breakpad::client
|
|
||||||
)
|
|
||||||
list(APPEND DEFINES
|
|
||||||
PUBLIC
|
|
||||||
-DUSE_BREAKPAD
|
|
||||||
PRIVATE
|
|
||||||
-DCRASHREPORTER_PROGRAM_NAME="$<TARGET_FILE_NAME:crashreporter>"
|
|
||||||
)
|
|
||||||
|
|
||||||
if(WIN32)
|
|
||||||
list(APPEND SOURCES
|
|
||||||
PRIVATE
|
|
||||||
internal/win32/CrashReportContext.h
|
|
||||||
internal/win32/CrashReportContext.cpp
|
|
||||||
)
|
|
||||||
elseif(UNIX)
|
|
||||||
list(APPEND SOURCES
|
|
||||||
PRIVATE
|
|
||||||
internal/unix/CrashReportContext.h
|
|
||||||
internal/unix/CrashReportContext.cpp)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
target_include_directories(${TARGET} ${INCLUDES})
|
|
||||||
target_sources(${TARGET} ${SOURCES})
|
|
||||||
target_link_libraries(${TARGET} ${LIBRARIES})
|
|
||||||
target_compile_definitions(${TARGET} ${DEFINES})
|
|
||||||
|
|
||||||
organize_source( "${TARGET_ROOT}" "" "${SOURCES}" )
|
|
@ -1,41 +0,0 @@
|
|||||||
#Adds a Crash Reporting dialog which may be invoked by a crashing program
|
|
||||||
|
|
||||||
set(TARGET crashreporter)
|
|
||||||
set(TARGET_ROOT ${CMAKE_CURRENT_SOURCE_DIR})
|
|
||||||
|
|
||||||
message( STATUS "========== Configuring ${TARGET} ==========" )
|
|
||||||
|
|
||||||
set(SOURCES
|
|
||||||
PRIVATE
|
|
||||||
warning.xpm
|
|
||||||
CrashReportApp.h
|
|
||||||
CrashReportApp.cpp
|
|
||||||
)
|
|
||||||
|
|
||||||
add_executable(${TARGET})
|
|
||||||
target_sources(${TARGET} ${SOURCES})
|
|
||||||
target_link_libraries(${TARGET} breakpad::processor breakpad::sender wxwidgets::wxwidgets)
|
|
||||||
|
|
||||||
if(WIN32)
|
|
||||||
set_target_properties(${TARGET} PROPERTIES WIN32_EXECUTABLE ON)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if( CMAKE_SYSTEM_NAME MATCHES "Darwin" )
|
|
||||||
add_custom_command(
|
|
||||||
TARGET
|
|
||||||
${TARGET}
|
|
||||||
COMMAND
|
|
||||||
${CMAKE_COMMAND} -D SRC="${_EXEDIR}/crashreporter"
|
|
||||||
-D DST="${_PKGLIB}"
|
|
||||||
-D WXWIN="${_SHARED_PROXY_BASE_PATH}/$<CONFIG>"
|
|
||||||
-P ${AUDACITY_MODULE_PATH}/CopyLibs.cmake
|
|
||||||
POST_BUILD
|
|
||||||
)
|
|
||||||
elseif(UNIX)
|
|
||||||
target_compile_definitions(${TARGET} PRIVATE -DINSTALL_PREFIX="${CMAKE_INSTALL_PREFIX}")
|
|
||||||
install(TARGETS ${TARGET} RUNTIME)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
set_target_property_all( ${TARGET} RUNTIME_OUTPUT_DIRECTORY "${_EXEDIR}" )
|
|
||||||
|
|
||||||
organize_source( "${TARGET_ROOT}" "" "${SOURCES}" )
|
|
@ -1,464 +0,0 @@
|
|||||||
#include "CrashReportApp.h"
|
|
||||||
|
|
||||||
#include <sstream>
|
|
||||||
#include <memory>
|
|
||||||
|
|
||||||
#include <wx/cmdline.h>
|
|
||||||
#include <wx/chartype.h>
|
|
||||||
#include <wx/artprov.h>
|
|
||||||
#include <wx/filename.h>
|
|
||||||
#include <wx/stdpaths.h>
|
|
||||||
|
|
||||||
#include "google_breakpad/processor/basic_source_line_resolver.h"
|
|
||||||
#include "google_breakpad/processor/minidump_processor.h"
|
|
||||||
#include "google_breakpad/processor/process_state.h"
|
|
||||||
#include "google_breakpad/processor/minidump.h"
|
|
||||||
#include "processor/stackwalk_common.h"
|
|
||||||
|
|
||||||
#include "warning.xpm"
|
|
||||||
|
|
||||||
//Temporary solution until lib-strings is added
|
|
||||||
#define XC(msg, ctx) (wxGetTranslation(msg, wxEmptyString, ctx))
|
|
||||||
|
|
||||||
#if defined(_WIN32)
|
|
||||||
#include <locale>
|
|
||||||
#include <codecvt>
|
|
||||||
#include "client/windows/sender/crash_report_sender.h"
|
|
||||||
|
|
||||||
namespace
|
|
||||||
{
|
|
||||||
std::wstring ToPlatformString(const std::string& utf8)
|
|
||||||
{
|
|
||||||
return std::wstring_convert<std::codecvt_utf8<std::wstring::traits_type::char_type>, std::wstring::traits_type::char_type>().from_bytes(utf8);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool SendMinidump(const std::string& url, const wxString& minidumpPath, const std::map<std::string, std::string>& arguments, const wxString& commentsFilePath)
|
|
||||||
{
|
|
||||||
std::map<std::wstring, std::wstring> files;
|
|
||||||
files[L"upload_file_minidump"] = minidumpPath.wc_str();
|
|
||||||
if (!commentsFilePath.empty())
|
|
||||||
{
|
|
||||||
files[wxFileName(commentsFilePath).GetFullName().wc_str()] = commentsFilePath.wc_str();
|
|
||||||
}
|
|
||||||
|
|
||||||
std::map<std::wstring, std::wstring> parameters;
|
|
||||||
for (auto& p : arguments)
|
|
||||||
{
|
|
||||||
parameters[ToPlatformString(p.first)] = ToPlatformString(p.second);
|
|
||||||
}
|
|
||||||
|
|
||||||
google_breakpad::CrashReportSender sender(L"");
|
|
||||||
|
|
||||||
auto result = sender.SendCrashReport(
|
|
||||||
ToPlatformString(url),
|
|
||||||
parameters,
|
|
||||||
files,
|
|
||||||
nullptr
|
|
||||||
);
|
|
||||||
return result == google_breakpad::RESULT_SUCCEEDED;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
|
|
||||||
#include "common/linux/http_upload.h"
|
|
||||||
|
|
||||||
namespace
|
|
||||||
{
|
|
||||||
bool SendMinidump(const std::string& url, const wxString& minidumpPath, const std::map<std::string, std::string>& arguments, const wxString& commentsFilePath)
|
|
||||||
{
|
|
||||||
std::map<std::string, std::string> files;
|
|
||||||
files["upload_file_minidump"] = minidumpPath.ToStdString();
|
|
||||||
if (!commentsFilePath.empty())
|
|
||||||
{
|
|
||||||
files["comments.txt"] = commentsFilePath.ToStdString();
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string response, error;
|
|
||||||
bool success = google_breakpad::HTTPUpload::SendRequest(
|
|
||||||
url,
|
|
||||||
arguments,
|
|
||||||
files,
|
|
||||||
std::string(),
|
|
||||||
std::string(),
|
|
||||||
std::string(),
|
|
||||||
&response,
|
|
||||||
NULL,
|
|
||||||
&error);
|
|
||||||
|
|
||||||
return success;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
IMPLEMENT_APP(CrashReportApp);
|
|
||||||
namespace
|
|
||||||
{
|
|
||||||
std::map<std::string, std::string> parseArguments(const std::string& str)
|
|
||||||
{
|
|
||||||
int TOKEN_IDENTIFIER{ 0 };
|
|
||||||
constexpr int TOKEN_EQ{ 1 };
|
|
||||||
constexpr int TOKEN_COMMA{ 2 };
|
|
||||||
constexpr int TOKEN_VALUE{ 3 };
|
|
||||||
|
|
||||||
int i = 0;
|
|
||||||
|
|
||||||
std::string key;
|
|
||||||
int state = TOKEN_COMMA;
|
|
||||||
std::map<std::string, std::string> result;
|
|
||||||
while (true)
|
|
||||||
{
|
|
||||||
if (str[i] == 0)
|
|
||||||
break;
|
|
||||||
else if (isspace(str[i]))
|
|
||||||
++i;
|
|
||||||
else if (isalpha(str[i]))
|
|
||||||
{
|
|
||||||
if (state != TOKEN_COMMA)
|
|
||||||
throw std::logic_error("malformed parameters string: unexpected identifier");
|
|
||||||
|
|
||||||
int begin = i;
|
|
||||||
while (isalnum(str[i]))
|
|
||||||
++i;
|
|
||||||
|
|
||||||
key = str.substr(begin, i - begin);
|
|
||||||
state = TOKEN_IDENTIFIER;
|
|
||||||
}
|
|
||||||
else if (str[i] == '=')
|
|
||||||
{
|
|
||||||
if (state != TOKEN_IDENTIFIER)
|
|
||||||
throw std::logic_error("malformed parameters string: unexpected '=' symbol");
|
|
||||||
++i;
|
|
||||||
state = TOKEN_EQ;
|
|
||||||
}
|
|
||||||
else if (str[i] == '\"')
|
|
||||||
{
|
|
||||||
if (state != TOKEN_EQ)
|
|
||||||
throw std::logic_error("malformed parameters string: unexpected '\"' symbol");
|
|
||||||
|
|
||||||
int begin = ++i;
|
|
||||||
while (true)
|
|
||||||
{
|
|
||||||
if (str[i] == 0)
|
|
||||||
throw std::logic_error("unterminated string literal");
|
|
||||||
else if (str[i] == '\"')
|
|
||||||
{
|
|
||||||
if (i > begin)
|
|
||||||
result[key] = str.substr(begin, i - begin);
|
|
||||||
else
|
|
||||||
result[key] = std::string();
|
|
||||||
++i;
|
|
||||||
state = TOKEN_VALUE;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
++i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (str[i] == ',')
|
|
||||||
{
|
|
||||||
if (state != TOKEN_VALUE)
|
|
||||||
throw std::logic_error("malformed parameters string: unexpected ',' symbol");
|
|
||||||
state = TOKEN_COMMA;
|
|
||||||
++i;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
throw std::logic_error("malformed parameters string");
|
|
||||||
}
|
|
||||||
if (state != TOKEN_VALUE)
|
|
||||||
throw std::logic_error("malformed parameters string");
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
void PrintMinidump(google_breakpad::Minidump& minidump)
|
|
||||||
{
|
|
||||||
google_breakpad::BasicSourceLineResolver resolver;
|
|
||||||
google_breakpad::MinidumpProcessor minidumpProcessor(nullptr, &resolver);
|
|
||||||
google_breakpad::MinidumpThreadList::set_max_threads(std::numeric_limits<uint32_t>::max());
|
|
||||||
google_breakpad::MinidumpMemoryList::set_max_regions(std::numeric_limits<uint32_t>::max());
|
|
||||||
|
|
||||||
google_breakpad::ProcessState processState;
|
|
||||||
|
|
||||||
if (minidumpProcessor.Process(&minidump, &processState) != google_breakpad::PROCESS_OK)
|
|
||||||
{
|
|
||||||
printf("Failed to process minidump");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
google_breakpad::PrintProcessState(processState, true, &resolver);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
wxString MakeDumpString(google_breakpad::Minidump& minidump, const wxString& temp)
|
|
||||||
{
|
|
||||||
#if _WIN32
|
|
||||||
auto stream = _wfreopen(temp.wc_str(), L"w+", stdout);
|
|
||||||
#else
|
|
||||||
auto stream = freopen(temp.utf8_str().data(), "w+", stdout);
|
|
||||||
#endif
|
|
||||||
if (stream == NULL)
|
|
||||||
throw std::runtime_error("Failed to print minidump: cannot open temp file");
|
|
||||||
PrintMinidump(minidump);
|
|
||||||
fflush(stdout);
|
|
||||||
|
|
||||||
auto length = ftell(stream);
|
|
||||||
std::vector<char> bytes(length);
|
|
||||||
fseek(stream, 0, SEEK_SET);
|
|
||||||
fread(&bytes[0], 1, length, stream);
|
|
||||||
fclose(stream);
|
|
||||||
|
|
||||||
#if _WIN32
|
|
||||||
_wremove(temp.wc_str());
|
|
||||||
#else
|
|
||||||
remove(temp.utf8_str().data());
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return wxString::From8BitData(&bytes[0], bytes.size());
|
|
||||||
}
|
|
||||||
|
|
||||||
wxString MakeHeaderString(google_breakpad::Minidump& minidump)
|
|
||||||
{
|
|
||||||
if (auto exception = minidump.GetException())
|
|
||||||
{
|
|
||||||
if (auto rawException = exception->exception())
|
|
||||||
{
|
|
||||||
// i18n-hint C++ programming assertion
|
|
||||||
return wxString::Format(_("Exception code 0x%x"), rawException->exception_record.exception_code);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// i18n-hint C++ programming assertion
|
|
||||||
return _("Unknown exception");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (auto assertion = minidump.GetAssertion())
|
|
||||||
{
|
|
||||||
auto expression = assertion->expression();
|
|
||||||
if (!expression.empty())
|
|
||||||
{
|
|
||||||
return expression;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return _("Unknown error");
|
|
||||||
}
|
|
||||||
|
|
||||||
void DoShowCrashReportFrame(const wxString& header, const wxString& dump, const std::function<bool(const wxString& comment)>& onSend)
|
|
||||||
{
|
|
||||||
static constexpr int MaxUserCommentLength = 2000;
|
|
||||||
|
|
||||||
auto frame = new wxFrame(
|
|
||||||
nullptr,
|
|
||||||
wxID_ANY,
|
|
||||||
_("Problem Report for Audacity"),
|
|
||||||
wxDefaultPosition,
|
|
||||||
wxDefaultSize,
|
|
||||||
wxDEFAULT_FRAME_STYLE & ~(wxRESIZE_BORDER | wxMAXIMIZE_BOX)//disable frame resize
|
|
||||||
);
|
|
||||||
frame->SetOwnBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_FRAMEBK));
|
|
||||||
|
|
||||||
auto mainLayout = new wxBoxSizer(wxVERTICAL);
|
|
||||||
|
|
||||||
auto headerText = new wxStaticText(frame, wxID_ANY, header);
|
|
||||||
headerText->SetFont(wxFont(wxFontInfo().Bold()));
|
|
||||||
|
|
||||||
auto headerLayout = new wxBoxSizer(wxHORIZONTAL);
|
|
||||||
headerLayout->Add(new wxStaticBitmap(frame, wxID_ANY, wxIcon(warning)));
|
|
||||||
headerLayout->AddSpacer(5);
|
|
||||||
headerLayout->Add(headerText, wxSizerFlags().Align(wxALIGN_CENTER_VERTICAL));
|
|
||||||
|
|
||||||
auto buttonsLayout = new wxBoxSizer(wxHORIZONTAL);
|
|
||||||
|
|
||||||
wxTextCtrl* commentCtrl = nullptr;
|
|
||||||
if (onSend != nullptr)
|
|
||||||
{
|
|
||||||
commentCtrl = new wxTextCtrl(frame, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize(500, 100), wxTE_MULTILINE);
|
|
||||||
commentCtrl->SetMaxLength(MaxUserCommentLength);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (onSend != nullptr)
|
|
||||||
{
|
|
||||||
auto okButton = new wxButton(frame, wxID_ANY, XC("&Don't send", "crash reporter button"));
|
|
||||||
auto sendButton = new wxButton(frame, wxID_ANY, XC("&Send", "crash reporter button"));
|
|
||||||
|
|
||||||
okButton->Bind(wxEVT_BUTTON, [frame](wxCommandEvent&)
|
|
||||||
{
|
|
||||||
frame->Close(true);
|
|
||||||
});
|
|
||||||
sendButton->Bind(wxEVT_BUTTON, [frame, commentCtrl, onSend](wxCommandEvent&)
|
|
||||||
{
|
|
||||||
if (onSend(commentCtrl->GetValue()))
|
|
||||||
{
|
|
||||||
frame->Close(true);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
buttonsLayout->Add(okButton);
|
|
||||||
buttonsLayout->AddSpacer(5);
|
|
||||||
buttonsLayout->Add(sendButton);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
auto okButton = new wxButton(frame, wxID_OK, wxT("OK"));
|
|
||||||
okButton->Bind(wxEVT_BUTTON, [frame](wxCommandEvent&)
|
|
||||||
{
|
|
||||||
frame->Close(true);
|
|
||||||
});
|
|
||||||
buttonsLayout->Add(okButton);
|
|
||||||
}
|
|
||||||
|
|
||||||
mainLayout->Add(headerLayout, wxSizerFlags().Border(wxALL));
|
|
||||||
if (onSend != nullptr)
|
|
||||||
{
|
|
||||||
mainLayout->AddSpacer(5);
|
|
||||||
mainLayout->Add(new wxStaticText(frame, wxID_ANY, _("Click \"Send\" to submit the report to Audacity. This information is collected anonymously.")), wxSizerFlags().Border(wxALL));
|
|
||||||
}
|
|
||||||
mainLayout->AddSpacer(10);
|
|
||||||
mainLayout->Add(new wxStaticText(frame, wxID_ANY, _("Problem details")), wxSizerFlags().Border(wxALL));
|
|
||||||
|
|
||||||
auto dumpTextCtrl = new wxTextCtrl(frame, wxID_ANY, dump, wxDefaultPosition, wxSize(500, 300), wxTE_RICH | wxTE_READONLY | wxTE_MULTILINE | wxTE_DONTWRAP);
|
|
||||||
dumpTextCtrl->SetFont(wxFont(wxFontInfo().Family(wxFONTFAMILY_TELETYPE)));
|
|
||||||
dumpTextCtrl->ShowPosition(0);//scroll to top
|
|
||||||
mainLayout->Add(dumpTextCtrl, wxSizerFlags().Border(wxALL).Expand());
|
|
||||||
|
|
||||||
if (onSend != nullptr)
|
|
||||||
{
|
|
||||||
mainLayout->AddSpacer(10);
|
|
||||||
mainLayout->Add(new wxStaticText(frame, wxID_ANY, _("Comments")), wxSizerFlags().Border(wxALL));
|
|
||||||
mainLayout->Add(commentCtrl, wxSizerFlags().Border(wxALL).Expand());
|
|
||||||
}
|
|
||||||
|
|
||||||
mainLayout->Add(buttonsLayout, wxSizerFlags().Border(wxALL).Align(wxALIGN_RIGHT));
|
|
||||||
frame->SetSizerAndFit(mainLayout);
|
|
||||||
|
|
||||||
frame->Show(true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool CrashReportApp::OnInit()
|
|
||||||
{
|
|
||||||
if (!wxApp::OnInit())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (mSilent)
|
|
||||||
{
|
|
||||||
if (!mURL.empty())
|
|
||||||
SendMinidump(mURL, mMinidumpPath, mArguments, wxEmptyString);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
static std::unique_ptr<wxLocale> sLocale(new wxLocale(wxLANGUAGE_DEFAULT));
|
|
||||||
#if defined(__WXOSX__)
|
|
||||||
sLocale->AddCatalogLookupPathPrefix(wxT("../Resources"));
|
|
||||||
#elif defined(__WXMSW__)
|
|
||||||
sLocale->AddCatalogLookupPathPrefix(wxT("Languages"));
|
|
||||||
#elif defined(__WXGTK__)
|
|
||||||
sLocale->AddCatalogLookupPathPrefix(wxT("./locale"));
|
|
||||||
sLocale->AddCatalogLookupPathPrefix(wxString::Format(wxT("%s/share/locale"), wxT(INSTALL_PREFIX)));
|
|
||||||
#endif
|
|
||||||
sLocale->AddCatalog("audacity");
|
|
||||||
sLocale->AddCatalog("wxstd");
|
|
||||||
|
|
||||||
google_breakpad::Minidump minidump(mMinidumpPath.ToStdString(), false);
|
|
||||||
if (minidump.Read())
|
|
||||||
{
|
|
||||||
SetExitOnFrameDelete(true);
|
|
||||||
|
|
||||||
wxFileName temp(mMinidumpPath);
|
|
||||||
temp.SetExt("tmp");
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
ShowCrashReport(MakeHeaderString(minidump), MakeDumpString(minidump, temp.GetFullPath()));
|
|
||||||
}
|
|
||||||
catch (std::exception& e)
|
|
||||||
{
|
|
||||||
wxMessageBox(e.what());
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CrashReportApp::OnInitCmdLine(wxCmdLineParser& parser)
|
|
||||||
{
|
|
||||||
static const wxCmdLineEntryDesc cmdLineEntryDesc[] =
|
|
||||||
{
|
|
||||||
{ wxCMD_LINE_SWITCH, "h", "help", "Display help on the command line parameters", wxCMD_LINE_VAL_NONE, wxCMD_LINE_OPTION_HELP },
|
|
||||||
{ wxCMD_LINE_SWITCH, "s", "silent", "Send without displaying the confirmation dialog" },
|
|
||||||
{ wxCMD_LINE_OPTION, "u", "url", "Crash report server URL", wxCMD_LINE_VAL_STRING, wxCMD_LINE_PARAM_OPTIONAL },
|
|
||||||
{ wxCMD_LINE_OPTION, "a", "args", "A set of arguments to send", wxCMD_LINE_VAL_STRING, wxCMD_LINE_PARAM_OPTIONAL },
|
|
||||||
{ wxCMD_LINE_PARAM, NULL, NULL, "path to minidump file", wxCMD_LINE_VAL_STRING, wxCMD_LINE_OPTION_MANDATORY },
|
|
||||||
{ wxCMD_LINE_NONE }
|
|
||||||
};
|
|
||||||
|
|
||||||
parser.SetDesc(cmdLineEntryDesc);
|
|
||||||
|
|
||||||
wxApp::OnInitCmdLine(parser);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CrashReportApp::OnCmdLineParsed(wxCmdLineParser& parser)
|
|
||||||
{
|
|
||||||
wxString url;
|
|
||||||
wxString arguments;
|
|
||||||
if (parser.Found("u", &url))
|
|
||||||
{
|
|
||||||
mURL = url.ToStdString();
|
|
||||||
}
|
|
||||||
if (parser.Found("a", &arguments))
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
mArguments = parseArguments(arguments.ToStdString());
|
|
||||||
}
|
|
||||||
catch (std::exception& e)
|
|
||||||
{
|
|
||||||
wxMessageBox(e.what());
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
mMinidumpPath = parser.GetParam(0);
|
|
||||||
mSilent = parser.Found("s");
|
|
||||||
|
|
||||||
return wxApp::OnCmdLineParsed(parser);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CrashReportApp::ShowCrashReport(const wxString& header, const wxString& text)
|
|
||||||
{
|
|
||||||
if (mURL.empty())
|
|
||||||
{
|
|
||||||
DoShowCrashReportFrame(header, text, nullptr);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
DoShowCrashReportFrame(header, text, [this](const wxString& comments)
|
|
||||||
{
|
|
||||||
wxString commentsFilePath;
|
|
||||||
if (!comments.empty())
|
|
||||||
{
|
|
||||||
wxFileName temp(mMinidumpPath);
|
|
||||||
temp.SetName(temp.GetName() + "-comments");
|
|
||||||
temp.SetExt("txt");
|
|
||||||
commentsFilePath = temp.GetFullPath();
|
|
||||||
wxFile file;
|
|
||||||
if (file.Open(commentsFilePath, wxFile::write))
|
|
||||||
{
|
|
||||||
file.Write(comments);
|
|
||||||
file.Close();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
auto result = SendMinidump(mURL, mMinidumpPath, mArguments, commentsFilePath);
|
|
||||||
if (!commentsFilePath.empty())
|
|
||||||
wxRemoveFile(commentsFilePath);
|
|
||||||
|
|
||||||
if (!result)
|
|
||||||
{
|
|
||||||
wxMessageBox(_("Failed to send crash report"));
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,36 +0,0 @@
|
|||||||
/*!********************************************************************
|
|
||||||
*
|
|
||||||
Audacity: A Digital Audio Editor
|
|
||||||
|
|
||||||
CrashReportApp.h
|
|
||||||
|
|
||||||
Vitaly Sverchinsky
|
|
||||||
|
|
||||||
**********************************************************************/
|
|
||||||
|
|
||||||
#include <wx/wx.h>
|
|
||||||
#include <map>
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
//! Crash reporter GUI application
|
|
||||||
/*! Used to send crash reports to a remote server, or view them.
|
|
||||||
* Shows brief report content, and allows user to send report to developers.
|
|
||||||
* Reporting URL and other parameters are specified as a command line arguments.
|
|
||||||
*/
|
|
||||||
class CrashReportApp final : public wxApp
|
|
||||||
{
|
|
||||||
std::string mURL;
|
|
||||||
wxString mMinidumpPath;
|
|
||||||
std::map<std::string, std::string> mArguments;
|
|
||||||
|
|
||||||
bool mSilent{ false };
|
|
||||||
public:
|
|
||||||
bool OnInit() override;
|
|
||||||
void OnInitCmdLine(wxCmdLineParser& parser) override;
|
|
||||||
bool OnCmdLineParsed(wxCmdLineParser& parser) override;
|
|
||||||
|
|
||||||
private:
|
|
||||||
void ShowCrashReport(const wxString& header, const wxString& text);
|
|
||||||
};
|
|
||||||
|
|
||||||
DECLARE_APP(CrashReportApp);
|
|
@ -1,138 +0,0 @@
|
|||||||
/* XPM */
|
|
||||||
static const char *warning[] = {
|
|
||||||
/* columns rows colors chars-per-pixel */
|
|
||||||
"24 24 108 2 ",
|
|
||||||
" c None",
|
|
||||||
". c black",
|
|
||||||
"X c #010100",
|
|
||||||
"o c #020200",
|
|
||||||
"O c #020201",
|
|
||||||
"+ c #070601",
|
|
||||||
"@ c #070701",
|
|
||||||
"# c #0E0C02",
|
|
||||||
"$ c #151204",
|
|
||||||
"% c #1C1804",
|
|
||||||
"& c #1F1A05",
|
|
||||||
"* c #261F00",
|
|
||||||
"= c #262000",
|
|
||||||
"- c #262005",
|
|
||||||
"; c #292305",
|
|
||||||
": c #2D2705",
|
|
||||||
"> c #312A06",
|
|
||||||
", c #403705",
|
|
||||||
"< c #413806",
|
|
||||||
"1 c #8F7300",
|
|
||||||
"2 c #957700",
|
|
||||||
"3 c #BA9500",
|
|
||||||
"4 c #B99600",
|
|
||||||
"5 c #E3B800",
|
|
||||||
"6 c #E5BA00",
|
|
||||||
"7 c #FEBB0B",
|
|
||||||
"8 c #FFBC08",
|
|
||||||
"9 c #FFBA0C",
|
|
||||||
"0 c #FFBF10",
|
|
||||||
"q c #FFBF11",
|
|
||||||
"w c #FFC000",
|
|
||||||
"e c #FFC100",
|
|
||||||
"r c #FFC202",
|
|
||||||
"t c #FFC400",
|
|
||||||
"y c #FFC500",
|
|
||||||
"u c #FFC700",
|
|
||||||
"i c #FFC307",
|
|
||||||
"p c #FFC800",
|
|
||||||
"a c #FFC900",
|
|
||||||
"s c #FECA00",
|
|
||||||
"d c #FFCB00",
|
|
||||||
"f c #FFCC00",
|
|
||||||
"g c #FFCD00",
|
|
||||||
"h c #FFCA04",
|
|
||||||
"j c #FFCF04",
|
|
||||||
"k c #FFC20B",
|
|
||||||
"l c #FFC00D",
|
|
||||||
"z c #FFC20D",
|
|
||||||
"x c #FFC00E",
|
|
||||||
"c c #FFCF0D",
|
|
||||||
"v c #FED004",
|
|
||||||
"b c #FFD104",
|
|
||||||
"n c #FFD00D",
|
|
||||||
"m c #FFD10D",
|
|
||||||
"M c #FFD20D",
|
|
||||||
"N c #FEC116",
|
|
||||||
"B c #FFCB14",
|
|
||||||
"V c #FFC61C",
|
|
||||||
"C c #FFCA1F",
|
|
||||||
"Z c #FFD215",
|
|
||||||
"A c #FFD11C",
|
|
||||||
"S c #FFD11D",
|
|
||||||
"D c #FFD31D",
|
|
||||||
"F c #FFD41D",
|
|
||||||
"G c #E6C327",
|
|
||||||
"H c #E7C527",
|
|
||||||
"J c #FFC621",
|
|
||||||
"K c #FFC525",
|
|
||||||
"L c #FFC624",
|
|
||||||
"P c #FFCC21",
|
|
||||||
"I c #FFCA25",
|
|
||||||
"U c #FFC927",
|
|
||||||
"Y c #FFCB26",
|
|
||||||
"T c #FFCC27",
|
|
||||||
"R c #FFCE27",
|
|
||||||
"E c #FFC22B",
|
|
||||||
"W c #FFC52A",
|
|
||||||
"Q c #FFC62C",
|
|
||||||
"! c #F2CE29",
|
|
||||||
"~ c #F3CF29",
|
|
||||||
"^ c #FFC828",
|
|
||||||
"/ c #FFCE28",
|
|
||||||
"( c #FFCC2A",
|
|
||||||
") c #FFCC2C",
|
|
||||||
"_ c #FFD423",
|
|
||||||
"` c #FFD623",
|
|
||||||
"' c #FFD226",
|
|
||||||
"] c #FFD527",
|
|
||||||
"[ c #F6D129",
|
|
||||||
"{ c #FFD129",
|
|
||||||
"} c #FFD229",
|
|
||||||
"| c #FFD22A",
|
|
||||||
" . c #FFD32A",
|
|
||||||
".. c #FDD42A",
|
|
||||||
"X. c #FCD52B",
|
|
||||||
"o. c #FFD42A",
|
|
||||||
"O. c #FFD52A",
|
|
||||||
"+. c #FFD52B",
|
|
||||||
"@. c #FFD62A",
|
|
||||||
"#. c #FFD62B",
|
|
||||||
"$. c #FFD72B",
|
|
||||||
"%. c #FFD828",
|
|
||||||
"&. c #FFD92B",
|
|
||||||
"*. c #FFDA2B",
|
|
||||||
"=. c #FFDA2C",
|
|
||||||
"-. c #FFC633",
|
|
||||||
";. c #FFC830",
|
|
||||||
":. c #FFCA31",
|
|
||||||
/* pixels */
|
|
||||||
" ",
|
|
||||||
" -.E ",
|
|
||||||
" / R ",
|
|
||||||
" U +.+.) ",
|
|
||||||
" ;.| +.+.| W ",
|
|
||||||
" U +.[ [ +.R ",
|
|
||||||
" ;.+.H X X G | J ",
|
|
||||||
" R +.! X X ! +.R ",
|
|
||||||
" L +.+.+.@ @ +.+.+.^ ",
|
|
||||||
" | +.+.=.# # *.+.+.| ",
|
|
||||||
" / +.+.+.*.$ $ *.+.+.+.U ",
|
|
||||||
" L ' ] ] ] *.% % *.] ] ] ' Q ",
|
|
||||||
" C ` ` ` ` ` - ; ` ` ` ` ` P ",
|
|
||||||
" J D D D D D D : > F D D D D D V ",
|
|
||||||
" B Z Z Z Z Z Z < , Z Z Z Z Z Z B ",
|
|
||||||
" k c n n n n n n n n n n n n n n c x ",
|
|
||||||
" q h j j j j j j j b b j j j j j j j h x ",
|
|
||||||
" i f f f f f f f 6 = * 5 f f f f f f f w ",
|
|
||||||
" 8 p p p p p p p p 3 X X 3 p p p f f p p p q ",
|
|
||||||
" w p p p p p p p p p 2 1 p p p p p p p p p w ",
|
|
||||||
"9 u u u u u u u u u u u u u u u u u u u u u u 7 ",
|
|
||||||
"N u u u u u u u u u u u u u u u u u u u u u u x ",
|
|
||||||
" ",
|
|
||||||
" "
|
|
||||||
};
|
|
@ -1,155 +0,0 @@
|
|||||||
/*!********************************************************************
|
|
||||||
*
|
|
||||||
Audacity: A Digital Audio Editor
|
|
||||||
|
|
||||||
CrashReportContext.cpp
|
|
||||||
|
|
||||||
Vitaly Sverchinsky
|
|
||||||
|
|
||||||
Some parts of the code are designed to operate while app is crashing,
|
|
||||||
so there may be some restrictions on heap usage. For more information
|
|
||||||
please read Breakpad documentation.
|
|
||||||
|
|
||||||
**********************************************************************/
|
|
||||||
#include "CrashReportContext.h"
|
|
||||||
|
|
||||||
#include <errno.h>
|
|
||||||
#include <map>
|
|
||||||
#include <sstream>
|
|
||||||
|
|
||||||
#if defined(__APPLE__)
|
|
||||||
#include "client/mac/handler/exception_handler.h"
|
|
||||||
#else
|
|
||||||
#include "client/linux/handler/exception_handler.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
bool SendReport(CrashReportContext* c, const char* minidumpPath)
|
|
||||||
{
|
|
||||||
auto pid = fork();
|
|
||||||
if(pid == 0)
|
|
||||||
{
|
|
||||||
if(c->mParameters[0] != 0)
|
|
||||||
{
|
|
||||||
execl(c->mSenderPath, CRASHREPORTER_PROGRAM_NAME, "-a", c->mParameters, "-u", c->mReportURL, minidumpPath, NULL);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
execl(c->mSenderPath, CRASHREPORTER_PROGRAM_NAME, "-u", c->mReportURL, minidumpPath, NULL);
|
|
||||||
}
|
|
||||||
fprintf(stderr, "Failed to start handler: %s\n", strerror(errno));
|
|
||||||
abort();
|
|
||||||
}
|
|
||||||
return pid != -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace
|
|
||||||
{
|
|
||||||
|
|
||||||
//converts parameters map to a string, so that the Crash Reporting program
|
|
||||||
//would understand them
|
|
||||||
std::string StringifyParameters(const std::map<std::string, std::string>& parameters)
|
|
||||||
{
|
|
||||||
std::stringstream stream;
|
|
||||||
|
|
||||||
std::size_t parameterIndex = 0;
|
|
||||||
std::size_t parametersCount = parameters.size();
|
|
||||||
for (auto& pair : parameters)
|
|
||||||
{
|
|
||||||
stream << pair.first.c_str() << "=\"" << pair.second.c_str() << "\"";
|
|
||||||
++parameterIndex;
|
|
||||||
if (parameterIndex < parametersCount)
|
|
||||||
stream << ",";
|
|
||||||
}
|
|
||||||
return stream.str();
|
|
||||||
}
|
|
||||||
|
|
||||||
//copy contents of src to a raw char dest buffer,
|
|
||||||
//returns false if dest is not large enough
|
|
||||||
bool StrcpyChecked(char* dest, size_t destsz, const std::string& src)
|
|
||||||
{
|
|
||||||
if(src.length() < destsz)
|
|
||||||
{
|
|
||||||
memcpy(dest, src.c_str(), src.length());
|
|
||||||
dest[src.length()] = '\0';
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if defined(__APPLE__)
|
|
||||||
|
|
||||||
static constexpr size_t MaxDumpPathLength{ 4096 };
|
|
||||||
static char DumpPath[MaxDumpPathLength];
|
|
||||||
|
|
||||||
bool DumpCallback(const char* dump_dir, const char* minidump_id, void* context, bool succeeded)
|
|
||||||
{
|
|
||||||
if(succeeded)
|
|
||||||
{
|
|
||||||
const int PathDumpLength = strlen(dump_dir) + strlen("/") + strlen(minidump_id) + strlen(".dmp");
|
|
||||||
if(PathDumpLength < MaxDumpPathLength)
|
|
||||||
{
|
|
||||||
strcpy(DumpPath, dump_dir);
|
|
||||||
strcat(DumpPath, "/");
|
|
||||||
strcat(DumpPath, minidump_id);
|
|
||||||
strcat(DumpPath, ".dmp");
|
|
||||||
auto crashReportContext = static_cast<CrashReportContext*>(context);
|
|
||||||
return SendReport(crashReportContext, DumpPath);
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return succeeded;
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
bool DumpCallback(const google_breakpad::MinidumpDescriptor& descriptor, void* context, bool succeeded)
|
|
||||||
{
|
|
||||||
if(succeeded)
|
|
||||||
{
|
|
||||||
auto crashReportContext = static_cast<CrashReportContext*>(context);
|
|
||||||
return SendReport(crashReportContext, descriptor.path());
|
|
||||||
}
|
|
||||||
return succeeded;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CrashReportContext::SetSenderPathUTF8(const std::string& path)
|
|
||||||
{
|
|
||||||
return StrcpyChecked(mSenderPath, MaxBufferLength, path + "/" + CRASHREPORTER_PROGRAM_NAME);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CrashReportContext::SetReportURL(const std::string& url)
|
|
||||||
{
|
|
||||||
return StrcpyChecked(mReportURL, MaxBufferLength, url);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CrashReportContext::SetParameters(const std::map<std::string, std::string>& p)
|
|
||||||
{
|
|
||||||
auto str = StringifyParameters(p);
|
|
||||||
return StrcpyChecked(mParameters, MaxBufferLength, str);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CrashReportContext::StartHandler(const std::string& databasePath)
|
|
||||||
{
|
|
||||||
//intentinal leak: error hooks may be useful while application is terminating
|
|
||||||
//CrashReportContext data should be alive too...
|
|
||||||
#if(__APPLE__)
|
|
||||||
static auto handler = new google_breakpad::ExceptionHandler(
|
|
||||||
databasePath,
|
|
||||||
nullptr,
|
|
||||||
DumpCallback,
|
|
||||||
this,
|
|
||||||
true,
|
|
||||||
nullptr
|
|
||||||
);
|
|
||||||
#else
|
|
||||||
google_breakpad::MinidumpDescriptor descriptor(databasePath);
|
|
||||||
static auto handler = new google_breakpad::ExceptionHandler(
|
|
||||||
descriptor,
|
|
||||||
nullptr,
|
|
||||||
DumpCallback,
|
|
||||||
this,
|
|
||||||
true,
|
|
||||||
-1
|
|
||||||
);
|
|
||||||
#endif
|
|
||||||
}
|
|
@ -1,43 +0,0 @@
|
|||||||
/*!********************************************************************
|
|
||||||
*
|
|
||||||
Audacity: A Digital Audio Editor
|
|
||||||
|
|
||||||
CrashReportContext.h
|
|
||||||
|
|
||||||
Vitaly Sverchinsky
|
|
||||||
|
|
||||||
**********************************************************************/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <string>
|
|
||||||
#include <map>
|
|
||||||
|
|
||||||
//!This object is for internal usage.
|
|
||||||
/*! Simple POD type, holds user data required to start handler.
|
|
||||||
* Fields are initialized with Set* methods,
|
|
||||||
* which may return false if internal buffer isn't large enough
|
|
||||||
* to store value passed as an argument.
|
|
||||||
* After initialization call StartHandler providing path to the
|
|
||||||
* database, where minidumps will be stored.
|
|
||||||
*/
|
|
||||||
class CrashReportContext
|
|
||||||
{
|
|
||||||
static constexpr size_t MaxBufferLength{ 2048 };
|
|
||||||
|
|
||||||
char mSenderPath[MaxBufferLength]{};
|
|
||||||
char mReportURL[MaxBufferLength]{};
|
|
||||||
char mParameters[MaxBufferLength]{};
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
bool SetSenderPathUTF8(const std::string& path);
|
|
||||||
bool SetReportURL(const std::string& url);
|
|
||||||
bool SetParameters(const std::map<std::string, std::string>& p);
|
|
||||||
|
|
||||||
void StartHandler(const std::string& databasePath);
|
|
||||||
|
|
||||||
private:
|
|
||||||
//helper function which need access to a private data, but should not be exposed to a public class interface
|
|
||||||
friend bool SendReport(CrashReportContext* ctx, const char* minidumpPath);
|
|
||||||
};
|
|
@ -1,165 +0,0 @@
|
|||||||
/*!********************************************************************
|
|
||||||
*
|
|
||||||
Audacity: A Digital Audio Editor
|
|
||||||
|
|
||||||
CrashReportContext.cpp
|
|
||||||
|
|
||||||
Vitaly Sverchinsky
|
|
||||||
|
|
||||||
Some parts of the code are designed to operate while app is crashing,
|
|
||||||
so there may be some restrictions on heap usage. For more information
|
|
||||||
please read Breakpad documentation.
|
|
||||||
|
|
||||||
**********************************************************************/
|
|
||||||
|
|
||||||
#include "CrashReportContext.h"
|
|
||||||
|
|
||||||
#include <locale>
|
|
||||||
#include <codecvt>
|
|
||||||
#include <sstream>
|
|
||||||
#include "client/windows/handler/exception_handler.h"
|
|
||||||
|
|
||||||
namespace
|
|
||||||
{
|
|
||||||
//copy src(null-terminated) to dst,
|
|
||||||
//returns false if dest is not large enough
|
|
||||||
bool StrcpyChecked(wchar_t* dest, size_t destsz, const wchar_t* src)
|
|
||||||
{
|
|
||||||
auto len = wcslen(src);
|
|
||||||
if (len < destsz)
|
|
||||||
{
|
|
||||||
memcpy(dest, src, sizeof(wchar_t) * len);
|
|
||||||
dest[len] = 0;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
//appends src(null-terminated) to dest, destsz is the total dest buffer size, not remaining
|
|
||||||
//returns false if dest is not large enough
|
|
||||||
bool StrcatChecked(wchar_t* dest, size_t destsz, const wchar_t* src)
|
|
||||||
{
|
|
||||||
auto srclen = wcslen(src);
|
|
||||||
auto dstlen = wcslen(dest);
|
|
||||||
if (srclen + dstlen < destsz)
|
|
||||||
{
|
|
||||||
memcpy(dest + dstlen, src, sizeof(wchar_t) * srclen);
|
|
||||||
dest[srclen + dstlen] = 0;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
//converts parameters map to a string, so that the Crash Reporting program
|
|
||||||
//would understand them
|
|
||||||
std::string StringifyParameters(const std::map<std::string, std::string>& parameters)
|
|
||||||
{
|
|
||||||
std::stringstream stream;
|
|
||||||
|
|
||||||
std::size_t parameterIndex = 0;
|
|
||||||
std::size_t parametersCount = parameters.size();
|
|
||||||
for (auto& pair : parameters)
|
|
||||||
{
|
|
||||||
stream << pair.first.c_str() << "=\\\"" << pair.second.c_str() << "\\\"";
|
|
||||||
++parameterIndex;
|
|
||||||
if (parameterIndex < parametersCount)
|
|
||||||
stream << ",";
|
|
||||||
}
|
|
||||||
return stream.str();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool MakeCommand(CrashReportContext* c, const wchar_t* path, const wchar_t* id)
|
|
||||||
{
|
|
||||||
//utility path
|
|
||||||
auto ok = StrcpyChecked(c->mCommand, CrashReportContext::MaxCommandLength, L"\"");
|
|
||||||
ok = ok && StrcatChecked(c->mCommand, CrashReportContext::MaxCommandLength, c->mSenderPath);
|
|
||||||
ok = ok && StrcatChecked(c->mCommand, CrashReportContext::MaxCommandLength, L"\"");
|
|
||||||
|
|
||||||
//parameters: /p "..."
|
|
||||||
if (ok && c->mParameters[0] != 0)
|
|
||||||
{
|
|
||||||
ok = ok && StrcatChecked(c->mCommand, CrashReportContext::MaxCommandLength, L" /a \"");
|
|
||||||
ok = ok && StrcatChecked(c->mCommand, CrashReportContext::MaxCommandLength, c->mParameters);
|
|
||||||
ok = ok && StrcatChecked(c->mCommand, CrashReportContext::MaxCommandLength, L"\"");
|
|
||||||
}
|
|
||||||
//crash report URL: /u https://...
|
|
||||||
ok = ok && StrcatChecked(c->mCommand, CrashReportContext::MaxBufferLength, L" /u \"");
|
|
||||||
ok = ok && StrcatChecked(c->mCommand, CrashReportContext::MaxBufferLength, c->mReportURL);
|
|
||||||
ok = ok && StrcatChecked(c->mCommand, CrashReportContext::MaxBufferLength, L"\" ");
|
|
||||||
//minidump path: path/to/minidump.dmp
|
|
||||||
ok = ok && StrcatChecked(c->mCommand, CrashReportContext::MaxCommandLength, L" \"");
|
|
||||||
ok = ok && StrcatChecked(c->mCommand, CrashReportContext::MaxCommandLength, path);
|
|
||||||
ok = ok && StrcatChecked(c->mCommand, CrashReportContext::MaxCommandLength, L"\\");
|
|
||||||
ok = ok && StrcatChecked(c->mCommand, CrashReportContext::MaxCommandLength, id);
|
|
||||||
ok = ok && StrcatChecked(c->mCommand, CrashReportContext::MaxCommandLength, L".dmp\"");
|
|
||||||
return ok;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool SendReport(CrashReportContext* c, const wchar_t* path, const wchar_t* id)
|
|
||||||
{
|
|
||||||
if (!MakeCommand(c, path, id))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
STARTUPINFOW si;
|
|
||||||
ZeroMemory(&si, sizeof(si));
|
|
||||||
si.cb = sizeof(si);
|
|
||||||
si.dwFlags = STARTF_USESHOWWINDOW;
|
|
||||||
si.wShowWindow = SW_SHOW;
|
|
||||||
|
|
||||||
PROCESS_INFORMATION pi;
|
|
||||||
ZeroMemory(&pi, sizeof(pi));
|
|
||||||
|
|
||||||
if (CreateProcessW(NULL, c->mCommand, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi))
|
|
||||||
{
|
|
||||||
CloseHandle(pi.hProcess);
|
|
||||||
CloseHandle(pi.hThread);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool UploadReport(
|
|
||||||
const wchar_t* dump_path,
|
|
||||||
const wchar_t* minidump_id,
|
|
||||||
void* context,
|
|
||||||
EXCEPTION_POINTERS* /*exinfo*/,
|
|
||||||
MDRawAssertionInfo* /*assertion*/,
|
|
||||||
bool succeeded)
|
|
||||||
{
|
|
||||||
CrashReportContext* crashReportContext = static_cast<CrashReportContext*>(context);
|
|
||||||
if (!SendReport(crashReportContext, dump_path, minidump_id))
|
|
||||||
return false;
|
|
||||||
return succeeded;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CrashReportContext::SetSenderPathUTF8(const std::string& path)
|
|
||||||
{
|
|
||||||
auto fullpath = path + "\\" + CRASHREPORTER_PROGRAM_NAME;
|
|
||||||
return StrcpyChecked(mSenderPath, MaxBufferLength, std::wstring_convert<std::codecvt_utf8<wchar_t>, wchar_t>().from_bytes(fullpath).c_str());
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CrashReportContext::SetReportURL(const std::string& url)
|
|
||||||
{
|
|
||||||
return StrcpyChecked(mReportURL, MaxBufferLength, std::wstring(url.begin(), url.end()).c_str());
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CrashReportContext::SetParameters(const std::map<std::string, std::string>& p)
|
|
||||||
{
|
|
||||||
auto str = StringifyParameters(p);
|
|
||||||
return StrcpyChecked(mParameters, MaxBufferLength, std::wstring(str.begin(), str.end()).c_str());
|
|
||||||
}
|
|
||||||
|
|
||||||
void CrashReportContext::StartHandler(const std::string& databasePath)
|
|
||||||
{
|
|
||||||
//intentinal leak: error hooks may be useful while application is terminating
|
|
||||||
//CrashReportContext data should be alive too...
|
|
||||||
static auto handler = new google_breakpad::ExceptionHandler(
|
|
||||||
std::wstring_convert<std::codecvt_utf8<wchar_t>, wchar_t>().from_bytes(databasePath),
|
|
||||||
NULL,
|
|
||||||
UploadReport,
|
|
||||||
this,
|
|
||||||
google_breakpad::ExceptionHandler::HANDLER_ALL);
|
|
||||||
}
|
|
||||||
|
|
@ -1,47 +0,0 @@
|
|||||||
/*!********************************************************************
|
|
||||||
*
|
|
||||||
Audacity: A Digital Audio Editor
|
|
||||||
|
|
||||||
CrashReportContext.h
|
|
||||||
|
|
||||||
Vitaly Sverchinsky
|
|
||||||
|
|
||||||
**********************************************************************/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <string>
|
|
||||||
#include <map>
|
|
||||||
|
|
||||||
//!This object is for internal usage.
|
|
||||||
/*! Simple POD type, holds user data required to start handler.
|
|
||||||
* Fields are initialized with Set* methods,
|
|
||||||
* which may return false if internal buffer isn't large enough
|
|
||||||
* to store value passed as an argument.
|
|
||||||
* After initialization call StartHandler providing path to the
|
|
||||||
* database, where minidumps will be stored.
|
|
||||||
*/
|
|
||||||
class CrashReportContext final
|
|
||||||
{
|
|
||||||
static constexpr size_t MaxBufferLength{ 2048 };
|
|
||||||
static constexpr size_t MaxCommandLength{ 8192 };
|
|
||||||
|
|
||||||
wchar_t mSenderPath[MaxBufferLength]{};
|
|
||||||
wchar_t mReportURL[MaxBufferLength]{};
|
|
||||||
wchar_t mParameters[MaxBufferLength]{};
|
|
||||||
|
|
||||||
//this is a buffer where the command will be built at runtime
|
|
||||||
wchar_t mCommand[MaxCommandLength]{};
|
|
||||||
|
|
||||||
public:
|
|
||||||
bool SetSenderPathUTF8(const std::string& path);
|
|
||||||
bool SetReportURL(const std::string& path);
|
|
||||||
bool SetParameters(const std::map<std::string, std::string>& p);
|
|
||||||
|
|
||||||
void StartHandler(const std::string& databasePath);
|
|
||||||
|
|
||||||
private:
|
|
||||||
//helper functions which need access to a private data, but should not be exposed to a public class interface
|
|
||||||
friend bool MakeCommand(CrashReportContext* ctx, const wchar_t* path, const wchar_t* id);
|
|
||||||
friend bool SendReport(CrashReportContext* ctx, const wchar_t* path, const wchar_t* id);
|
|
||||||
};
|
|
@ -77,7 +77,6 @@ It handles initialization and termination by subclassing wxApp.
|
|||||||
#include "AudioIO.h"
|
#include "AudioIO.h"
|
||||||
#include "Benchmark.h"
|
#include "Benchmark.h"
|
||||||
#include "Clipboard.h"
|
#include "Clipboard.h"
|
||||||
#include "CrashReport.h" // for HAS_CRASH_REPORT
|
|
||||||
#include "commands/CommandHandler.h"
|
#include "commands/CommandHandler.h"
|
||||||
#include "commands/AppCommandEvent.h"
|
#include "commands/AppCommandEvent.h"
|
||||||
#include "widgets/ASlider.h"
|
#include "widgets/ASlider.h"
|
||||||
@ -123,10 +122,6 @@ It handles initialization and termination by subclassing wxApp.
|
|||||||
|
|
||||||
#include "import/Import.h"
|
#include "import/Import.h"
|
||||||
|
|
||||||
#if defined(USE_BREAKPAD)
|
|
||||||
#include "BreakpadConfigurer.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef EXPERIMENTAL_SCOREALIGN
|
#ifdef EXPERIMENTAL_SCOREALIGN
|
||||||
#include "effects/ScoreAlignDialog.h"
|
#include "effects/ScoreAlignDialog.h"
|
||||||
#endif
|
#endif
|
||||||
@ -382,29 +377,6 @@ void PopulatePreferences()
|
|||||||
gPrefs->Flush();
|
gPrefs->Flush();
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(USE_BREAKPAD)
|
|
||||||
void InitBreakpad()
|
|
||||||
{
|
|
||||||
wxFileName databasePath;
|
|
||||||
databasePath.SetPath(wxStandardPaths::Get().GetUserLocalDataDir());
|
|
||||||
databasePath.AppendDir("crashreports");
|
|
||||||
databasePath.Mkdir(wxS_DIR_DEFAULT, wxPATH_MKDIR_FULL);
|
|
||||||
|
|
||||||
if(databasePath.DirExists())
|
|
||||||
{
|
|
||||||
BreakpadConfigurer configurer;
|
|
||||||
configurer.SetDatabasePathUTF8(databasePath.GetPath().ToUTF8().data())
|
|
||||||
.SetSenderPathUTF8(wxFileName(wxStandardPaths::Get().GetExecutablePath()).GetPath().ToUTF8().data())
|
|
||||||
#if defined(CRASH_REPORT_URL)
|
|
||||||
.SetReportURL(CRASH_REPORT_URL)
|
|
||||||
#endif
|
|
||||||
.SetParameters({
|
|
||||||
{ "version", wxString(AUDACITY_VERSION_STRING).ToUTF8().data() }
|
|
||||||
})
|
|
||||||
.Start();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool gInited = false;
|
static bool gInited = false;
|
||||||
@ -952,10 +924,6 @@ wxLanguageInfo userLangs[] =
|
|||||||
|
|
||||||
void AudacityApp::OnFatalException()
|
void AudacityApp::OnFatalException()
|
||||||
{
|
{
|
||||||
#if defined(HAS_CRASH_REPORT)
|
|
||||||
CrashReport::Generate(wxDebugReport::Context_Exception);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
exit(-1);
|
exit(-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1020,15 +988,12 @@ bool AudacityApp::OnExceptionInMainLoop()
|
|||||||
AudacityApp::AudacityApp()
|
AudacityApp::AudacityApp()
|
||||||
{
|
{
|
||||||
#if defined(USE_BREAKPAD)
|
#if defined(USE_BREAKPAD)
|
||||||
InitBreakpad();
|
|
||||||
// Do not capture crashes in debug builds
|
// Do not capture crashes in debug builds
|
||||||
#elif !defined(_DEBUG)
|
#elif !defined(_DEBUG)
|
||||||
#if defined(HAS_CRASH_REPORT)
|
|
||||||
#if defined(wxUSE_ON_FATAL_EXCEPTION) && wxUSE_ON_FATAL_EXCEPTION
|
#if defined(wxUSE_ON_FATAL_EXCEPTION) && wxUSE_ON_FATAL_EXCEPTION
|
||||||
wxHandleFatalExceptions();
|
wxHandleFatalExceptions();
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
AudacityApp::~AudacityApp()
|
AudacityApp::~AudacityApp()
|
||||||
|
@ -120,8 +120,6 @@ list( APPEND SOURCES
|
|||||||
Clipboard.h
|
Clipboard.h
|
||||||
CommonCommandFlags.cpp
|
CommonCommandFlags.cpp
|
||||||
CommonCommandFlags.h
|
CommonCommandFlags.h
|
||||||
CrashReport.cpp
|
|
||||||
CrashReport.h
|
|
||||||
DarkThemeAsCeeCode.h
|
DarkThemeAsCeeCode.h
|
||||||
DBConnection.cpp
|
DBConnection.cpp
|
||||||
DBConnection.h
|
DBConnection.h
|
||||||
@ -1071,7 +1069,6 @@ list( APPEND LIBRARIES
|
|||||||
libsoxr
|
libsoxr
|
||||||
portaudio-v19
|
portaudio-v19
|
||||||
sqlite
|
sqlite
|
||||||
$<$<BOOL:${${_OPT}has_crashreports}>:crashreports>
|
|
||||||
$<$<BOOL:${USE_FFMPEG}>:ffmpeg>
|
$<$<BOOL:${USE_FFMPEG}>:ffmpeg>
|
||||||
$<$<BOOL:${USE_LIBID3TAG}>:libid3tag::libid3tag>
|
$<$<BOOL:${USE_LIBID3TAG}>:libid3tag::libid3tag>
|
||||||
$<$<BOOL:${USE_LIBFLAC}>:libflac>
|
$<$<BOOL:${USE_LIBFLAC}>:libflac>
|
||||||
@ -1294,10 +1291,6 @@ else()
|
|||||||
)
|
)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(CRASH_REPORT_URL)
|
|
||||||
list(APPEND DEFINES PRIVATE -DCRASH_REPORT_URL="${CRASH_REPORT_URL}")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
set_target_property_all( ${TARGET} RUNTIME_OUTPUT_NAME ${AUDACITY_NAME} )
|
set_target_property_all( ${TARGET} RUNTIME_OUTPUT_NAME ${AUDACITY_NAME} )
|
||||||
|
|
||||||
organize_source( "${TARGET_ROOT}/.." "include" "${HEADERS}" )
|
organize_source( "${TARGET_ROOT}/.." "include" "${HEADERS}" )
|
||||||
|
@ -1,119 +0,0 @@
|
|||||||
/**********************************************************************
|
|
||||||
|
|
||||||
Audacity: A Digital Audio Editor
|
|
||||||
|
|
||||||
CrashReport.cpp
|
|
||||||
|
|
||||||
*//*******************************************************************/
|
|
||||||
|
|
||||||
|
|
||||||
#include "CrashReport.h"
|
|
||||||
|
|
||||||
#if defined(HAS_CRASH_REPORT)
|
|
||||||
#include <atomic>
|
|
||||||
#include <thread>
|
|
||||||
|
|
||||||
#include <wx/progdlg.h>
|
|
||||||
|
|
||||||
#if defined(__WXMSW__)
|
|
||||||
#include <wx/evtloop.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "wxFileNameWrapper.h"
|
|
||||||
#include "AudacityLogger.h"
|
|
||||||
#include "AudioIOBase.h"
|
|
||||||
#include "FileNames.h"
|
|
||||||
#include "Internat.h"
|
|
||||||
#include "Languages.h"
|
|
||||||
#include "Project.h"
|
|
||||||
#include "ProjectFileIO.h"
|
|
||||||
#include "prefs/GUIPrefs.h"
|
|
||||||
#include "widgets/ErrorDialog.h"
|
|
||||||
|
|
||||||
namespace CrashReport {
|
|
||||||
|
|
||||||
void Generate(wxDebugReport::Context ctx)
|
|
||||||
{
|
|
||||||
wxDebugReportCompress rpt;
|
|
||||||
|
|
||||||
// Bug 1927: Seems there problems with wxStackWalker, so don't even include
|
|
||||||
// the stack trace or memory dump. The former is pretty much useless in Release
|
|
||||||
// builds anyway and none of use have the skill/time/desire to fiddle with the
|
|
||||||
// latter.
|
|
||||||
// rpt.AddAll(ctx);
|
|
||||||
|
|
||||||
{
|
|
||||||
// Provides a progress dialog with indeterminate mode
|
|
||||||
wxGenericProgressDialog pd(XO("Audacity Support Data").Translation(),
|
|
||||||
XO("This may take several seconds").Translation(),
|
|
||||||
300000, // range
|
|
||||||
nullptr, // parent
|
|
||||||
wxPD_APP_MODAL | wxPD_ELAPSED_TIME | wxPD_SMOOTH);
|
|
||||||
|
|
||||||
std::atomic_bool done = {false};
|
|
||||||
auto thread = std::thread([&]
|
|
||||||
{
|
|
||||||
wxFileNameWrapper fn{ FileNames::DataDir(), wxT("audacity.cfg") };
|
|
||||||
rpt.AddFile(fn.GetFullPath(), _TS("Audacity Configuration"));
|
|
||||||
rpt.AddFile(FileNames::PluginRegistry(), wxT("Plugin Registry"));
|
|
||||||
rpt.AddFile(FileNames::PluginSettings(), wxT("Plugin Settings"));
|
|
||||||
|
|
||||||
if (ctx == wxDebugReport::Context_Current)
|
|
||||||
{
|
|
||||||
auto saveLang = Languages::GetLangShort();
|
|
||||||
GUIPrefs::SetLang( wxT("en") );
|
|
||||||
auto cleanup = finally( [&]{ GUIPrefs::SetLang( saveLang ); } );
|
|
||||||
|
|
||||||
auto gAudioIO = AudioIOBase::Get();
|
|
||||||
rpt.AddText(wxT("audiodev.txt"), gAudioIO->GetDeviceInfo(), wxT("Audio Device Info"));
|
|
||||||
#ifdef EXPERIMENTAL_MIDI_OUT
|
|
||||||
rpt.AddText(wxT("mididev.txt"), gAudioIO->GetMidiDeviceInfo(), wxT("MIDI Device Info"));
|
|
||||||
#endif
|
|
||||||
auto project = GetActiveProject();
|
|
||||||
auto &projectFileIO = ProjectFileIO::Get( *project );
|
|
||||||
rpt.AddText(wxT("project.txt"), projectFileIO.GenerateDoc(), wxT("Active project doc"));
|
|
||||||
}
|
|
||||||
|
|
||||||
auto logger = AudacityLogger::Get();
|
|
||||||
if (logger)
|
|
||||||
{
|
|
||||||
rpt.AddText(wxT("log.txt"), logger->GetLog(), _TS("Audacity Log"));
|
|
||||||
}
|
|
||||||
|
|
||||||
done = true;
|
|
||||||
});
|
|
||||||
|
|
||||||
// Wait for information to be gathered
|
|
||||||
while (!done)
|
|
||||||
{
|
|
||||||
wxMilliSleep(50);
|
|
||||||
pd.Pulse();
|
|
||||||
}
|
|
||||||
thread.join();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ok = wxDebugReportPreviewStd().Show(rpt);
|
|
||||||
|
|
||||||
#if defined(__WXMSW__)
|
|
||||||
wxEventLoop::SetCriticalWindow(NULL);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (ok && rpt.Process())
|
|
||||||
{
|
|
||||||
AudacityTextEntryDialog dlg(nullptr,
|
|
||||||
XO("Report generated to:"),
|
|
||||||
XO("Audacity Support Data"),
|
|
||||||
rpt.GetCompressedFileName(),
|
|
||||||
wxOK | wxCENTER);
|
|
||||||
dlg.SetName(dlg.GetTitle());
|
|
||||||
dlg.ShowModal();
|
|
||||||
|
|
||||||
wxLogMessage(wxT("Report generated to: %s"),
|
|
||||||
rpt.GetCompressedFileName());
|
|
||||||
|
|
||||||
rpt.Reset();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
#endif
|
|
@ -1,36 +0,0 @@
|
|||||||
/**********************************************************************
|
|
||||||
|
|
||||||
Audacity: A Digital Audio Editor
|
|
||||||
|
|
||||||
CrashReport.h
|
|
||||||
|
|
||||||
Paul Licameli
|
|
||||||
split from AudacityApp.h
|
|
||||||
|
|
||||||
**********************************************************************/
|
|
||||||
|
|
||||||
#ifndef __AUDACITY_CRASH_REPORT__
|
|
||||||
#define __AUDACITY_CRASH_REPORT__
|
|
||||||
|
|
||||||
#undef HAS_CRASH_REPORT
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#if defined(EXPERIMENTAL_CRASH_REPORT)
|
|
||||||
|
|
||||||
#include <wx/setup.h> // for wxUSE* macros
|
|
||||||
#if defined(wxUSE_DEBUGREPORT) && wxUSE_DEBUGREPORT
|
|
||||||
#define HAS_CRASH_REPORT
|
|
||||||
#include <wx/debugrpt.h>
|
|
||||||
|
|
||||||
namespace CrashReport
|
|
||||||
{
|
|
||||||
AUDACITY_DLL_API
|
|
||||||
void Generate(wxDebugReport::Context ctx);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif
|
|
@ -175,10 +175,6 @@ set( EXPERIMENTAL_OPTIONS_LIST
|
|||||||
# scrolling past zero is enabled. Perhaps that lessens confusion.
|
# scrolling past zero is enabled. Perhaps that lessens confusion.
|
||||||
TWO_TONE_TIME_RULER
|
TWO_TONE_TIME_RULER
|
||||||
|
|
||||||
#Define to include crash reporting, if available in wxWidgets build
|
|
||||||
#This flag is used only in CrashReport.h; elsewhere use HAS_CRASH_REPORT
|
|
||||||
CRASH_REPORT
|
|
||||||
|
|
||||||
# Paul Licameli (PRL) 31 May 2015
|
# Paul Licameli (PRL) 31 May 2015
|
||||||
# Zero-padding factor for spectrograms can smooth the display of spectrograms by
|
# Zero-padding factor for spectrograms can smooth the display of spectrograms by
|
||||||
# interpolating in frequency domain.
|
# interpolating in frequency domain.
|
||||||
|
@ -9,7 +9,6 @@
|
|||||||
#include "../AudacityLogger.h"
|
#include "../AudacityLogger.h"
|
||||||
#include "../AudioIOBase.h"
|
#include "../AudioIOBase.h"
|
||||||
#include "../CommonCommandFlags.h"
|
#include "../CommonCommandFlags.h"
|
||||||
#include "../CrashReport.h" // for HAS_CRASH_REPORT
|
|
||||||
#include "../FileNames.h"
|
#include "../FileNames.h"
|
||||||
#include "../HelpText.h"
|
#include "../HelpText.h"
|
||||||
#include "../Menus.h"
|
#include "../Menus.h"
|
||||||
@ -348,18 +347,6 @@ void OnShowLog( const CommandContext &context )
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(HAS_CRASH_REPORT)
|
|
||||||
void OnCrashReport(const CommandContext &WXUNUSED(context) )
|
|
||||||
{
|
|
||||||
// Change to "1" to test a real crash
|
|
||||||
#if 0
|
|
||||||
char *p = 0;
|
|
||||||
*p = 1234;
|
|
||||||
#endif
|
|
||||||
CrashReport::Generate(wxDebugReport::Context_Current);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef IS_ALPHA
|
#ifdef IS_ALPHA
|
||||||
void OnSegfault(const CommandContext &)
|
void OnSegfault(const CommandContext &)
|
||||||
{
|
{
|
||||||
@ -543,9 +530,6 @@ BaseItemSharedPtr HelpMenu()
|
|||||||
#endif
|
#endif
|
||||||
Command( wxT("Log"), XXO("Show &Log..."), FN(OnShowLog),
|
Command( wxT("Log"), XXO("Show &Log..."), FN(OnShowLog),
|
||||||
AlwaysEnabledFlag ),
|
AlwaysEnabledFlag ),
|
||||||
#if defined(HAS_CRASH_REPORT)
|
|
||||||
Command( wxT("CrashReport"), XXO("&Generate Support Data..."),
|
|
||||||
FN(OnCrashReport), AlwaysEnabledFlag )
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef IS_ALPHA
|
#ifdef IS_ALPHA
|
||||||
|
Loading…
x
Reference in New Issue
Block a user