forked from mia/Aegisub
Extract crashlog writing from main.cpp
This commit is contained in:
parent
39823b5d89
commit
61b19a17e8
6 changed files with 139 additions and 66 deletions
|
@ -144,6 +144,7 @@
|
||||||
<ClInclude Include="$(SrcDir)command\command.h" />
|
<ClInclude Include="$(SrcDir)command\command.h" />
|
||||||
<ClInclude Include="$(SrcDir)compat.h" />
|
<ClInclude Include="$(SrcDir)compat.h" />
|
||||||
<ClInclude Include="$(SrcDir)config.h" />
|
<ClInclude Include="$(SrcDir)config.h" />
|
||||||
|
<ClInclude Include="$(SrcDir)crash_writer.h" />
|
||||||
<ClInclude Include="$(SrcDir)dialog_about.h" />
|
<ClInclude Include="$(SrcDir)dialog_about.h" />
|
||||||
<ClInclude Include="$(SrcDir)dialog_attachments.h" />
|
<ClInclude Include="$(SrcDir)dialog_attachments.h" />
|
||||||
<ClInclude Include="$(SrcDir)dialog_automation.h" />
|
<ClInclude Include="$(SrcDir)dialog_automation.h" />
|
||||||
|
@ -347,6 +348,7 @@
|
||||||
<ClCompile Include="$(SrcDir)command\video.cpp" />
|
<ClCompile Include="$(SrcDir)command\video.cpp" />
|
||||||
<ClCompile Include="$(SrcDir)command\vis_tool.cpp" />
|
<ClCompile Include="$(SrcDir)command\vis_tool.cpp" />
|
||||||
<ClCompile Include="$(SrcDir)compat.cpp" />
|
<ClCompile Include="$(SrcDir)compat.cpp" />
|
||||||
|
<ClCompile Include="$(SrcDir)crash_writer.cpp" />
|
||||||
<ClCompile Include="$(SrcDir)dialog_about.cpp" />
|
<ClCompile Include="$(SrcDir)dialog_about.cpp" />
|
||||||
<ClCompile Include="$(SrcDir)dialog_attachments.cpp" />
|
<ClCompile Include="$(SrcDir)dialog_attachments.cpp" />
|
||||||
<ClCompile Include="$(SrcDir)dialog_automation.cpp" />
|
<ClCompile Include="$(SrcDir)dialog_automation.cpp" />
|
||||||
|
|
|
@ -594,6 +594,9 @@
|
||||||
<ClInclude Include="$(SrcDir)dialog_log.h">
|
<ClInclude Include="$(SrcDir)dialog_log.h">
|
||||||
<Filter>Utilities\Logging</Filter>
|
<Filter>Utilities\Logging</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="$(SrcDir)crash_writer.h">
|
||||||
|
<Filter>Utilities\Logging</Filter>
|
||||||
|
</ClInclude>
|
||||||
<ClInclude Include="$(SrcDir)utils.h">
|
<ClInclude Include="$(SrcDir)utils.h">
|
||||||
<Filter>Utilities</Filter>
|
<Filter>Utilities</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
@ -1232,6 +1235,9 @@
|
||||||
<ClCompile Include="$(SrcDir)resolution_resampler.cpp">
|
<ClCompile Include="$(SrcDir)resolution_resampler.cpp">
|
||||||
<Filter>Features\Resolution resampler</Filter>
|
<Filter>Features\Resolution resampler</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="$(SrcDir)crash_writer.cpp">
|
||||||
|
<Filter>Utilities\Logging</Filter>
|
||||||
|
</ClCompile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ResourceCompile Include="$(SrcDir)res/res.rc">
|
<ResourceCompile Include="$(SrcDir)res/res.rc">
|
||||||
|
|
|
@ -154,6 +154,7 @@ SRC += \
|
||||||
colorspace.cpp \
|
colorspace.cpp \
|
||||||
colour_button.cpp \
|
colour_button.cpp \
|
||||||
compat.cpp \
|
compat.cpp \
|
||||||
|
crash_writer.cpp \
|
||||||
dialog_about.cpp \
|
dialog_about.cpp \
|
||||||
dialog_attachments.cpp \
|
dialog_attachments.cpp \
|
||||||
dialog_automation.cpp \
|
dialog_automation.cpp \
|
||||||
|
|
92
src/crash_writer.cpp
Normal file
92
src/crash_writer.cpp
Normal file
|
@ -0,0 +1,92 @@
|
||||||
|
// Copyright (c) 2014, Thomas Goyne <plorkyeran@aegisub.org>
|
||||||
|
//
|
||||||
|
// Permission to use, copy, modify, and distribute this software for any
|
||||||
|
// purpose with or without fee is hereby granted, provided that the above
|
||||||
|
// copyright notice and this permission notice appear in all copies.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
|
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||||
|
// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||||
|
// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||||
|
// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
//
|
||||||
|
// Aegisub Project http://www.aegisub.org/
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
#include "crash_writer.h"
|
||||||
|
|
||||||
|
#include "version.h"
|
||||||
|
|
||||||
|
#include <libaegisub/util.h>
|
||||||
|
|
||||||
|
#include <boost/filesystem/fstream.hpp>
|
||||||
|
#include <boost/format.hpp>
|
||||||
|
|
||||||
|
using namespace agi;
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
fs::path crashlog_path;
|
||||||
|
|
||||||
|
#if wxUSE_STACKWALKER == 1
|
||||||
|
class StackWalker : public wxStackWalker {
|
||||||
|
boost::filesystem::ofstream fp;
|
||||||
|
|
||||||
|
public:
|
||||||
|
StackWalker(std::string const& cause)
|
||||||
|
: fp(crashlog_path, std::ios::app)
|
||||||
|
{
|
||||||
|
if (!fp.good()) return;
|
||||||
|
|
||||||
|
fp << util::strftime("--- %y-%m-%d %H:%M:%S ------------------\n");
|
||||||
|
fp << boost::format("VER - %s\n") % GetAegisubLongVersionString();
|
||||||
|
fp << boost::format("FTL - Beginning stack dump for \"%s\": \n") % cause;
|
||||||
|
}
|
||||||
|
|
||||||
|
~StackWalker() {
|
||||||
|
if (!fp.good()) return;
|
||||||
|
|
||||||
|
fp << "End of stack dump.\n";
|
||||||
|
fp << "----------------------------------------\n\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
void OnStackFrame(wxStackFrame const& frame) override final {
|
||||||
|
if (!fp.good()) return;
|
||||||
|
|
||||||
|
fp << boost::format("%03u - %p: %s") % frame.GetLevel() % frame.GetAddress() % frame.GetName().utf8_str().data();
|
||||||
|
if (frame.HasSourceLocation())
|
||||||
|
fp << boost::format(" on %s:%u") % frame.GetFileName().utf8_str().data() % frame.GetLine();
|
||||||
|
|
||||||
|
fp << "\n";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace crash_writer {
|
||||||
|
void Initialize(fs::path const& path) {
|
||||||
|
crashlog_path = path / "crashlog.txt";
|
||||||
|
}
|
||||||
|
|
||||||
|
void Cleanup() { }
|
||||||
|
|
||||||
|
void Write() {
|
||||||
|
#if wxUSE_STACKWALKER == 1
|
||||||
|
StackWalker walker("Fatal exception");
|
||||||
|
walker.WalkFromException();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void Write(std::string const& error) {
|
||||||
|
boost::filesystem::ofstream file(crashlog_path, std::ios::app);
|
||||||
|
if (file.is_open()) {
|
||||||
|
file << util::strftime("--- %y-%m-%d %H:%M:%S ------------------\n");
|
||||||
|
file << boost::format("VER - %s\n") % GetAegisubLongVersionString();
|
||||||
|
file << boost::format("EXC - Aegisub has crashed with unhandled exception \"%s\".\n") % error;
|
||||||
|
file << "----------------------------------------\n\n";
|
||||||
|
file.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
27
src/crash_writer.h
Normal file
27
src/crash_writer.h
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
// Copyright (c) 2014, Thomas Goyne <plorkyeran@aegisub.org>
|
||||||
|
//
|
||||||
|
// Permission to use, copy, modify, and distribute this software for any
|
||||||
|
// purpose with or without fee is hereby granted, provided that the above
|
||||||
|
// copyright notice and this permission notice appear in all copies.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
|
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||||
|
// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||||
|
// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||||
|
// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
//
|
||||||
|
// Aegisub Project http://www.aegisub.org/
|
||||||
|
|
||||||
|
#include <libaegisub/fs_fwd.h>
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
namespace crash_writer {
|
||||||
|
void Initialize(agi::fs::path const& path);
|
||||||
|
void Cleanup();
|
||||||
|
|
||||||
|
void Write();
|
||||||
|
void Write(std::string const& error);
|
||||||
|
}
|
77
src/main.cpp
77
src/main.cpp
|
@ -34,6 +34,8 @@
|
||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
|
||||||
|
#include "main.h"
|
||||||
|
|
||||||
#include "command/command.h"
|
#include "command/command.h"
|
||||||
#include "include/aegisub/hotkey.h"
|
#include "include/aegisub/hotkey.h"
|
||||||
|
|
||||||
|
@ -41,18 +43,18 @@
|
||||||
#include "ass_file.h"
|
#include "ass_file.h"
|
||||||
#include "auto4_base.h"
|
#include "auto4_base.h"
|
||||||
#include "compat.h"
|
#include "compat.h"
|
||||||
|
#include "crash_writer.h"
|
||||||
#include "export_fixstyle.h"
|
#include "export_fixstyle.h"
|
||||||
#include "export_framerate.h"
|
#include "export_framerate.h"
|
||||||
#include "frame_main.h"
|
#include "frame_main.h"
|
||||||
#include "include/aegisub/context.h"
|
#include "include/aegisub/context.h"
|
||||||
#include "main.h"
|
|
||||||
#include "libresrc/libresrc.h"
|
#include "libresrc/libresrc.h"
|
||||||
#include "options.h"
|
#include "options.h"
|
||||||
#include "plugin_manager.h"
|
#include "plugin_manager.h"
|
||||||
#include "subs_controller.h"
|
#include "subs_controller.h"
|
||||||
#include "subtitle_format.h"
|
#include "subtitle_format.h"
|
||||||
#include "version.h"
|
|
||||||
#include "video_context.h"
|
#include "video_context.h"
|
||||||
|
#include "version.h"
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
|
|
||||||
#include <libaegisub/dispatch.h>
|
#include <libaegisub/dispatch.h>
|
||||||
|
@ -140,6 +142,7 @@ bool AegisubApp::OnInit() {
|
||||||
});
|
});
|
||||||
|
|
||||||
config::path = new agi::Path;
|
config::path = new agi::Path;
|
||||||
|
crash_writer::Initialize(config::path->Decode("?user"));
|
||||||
|
|
||||||
agi::log::log = new agi::log::LogSink;
|
agi::log::log = new agi::log::LogSink;
|
||||||
#ifdef _DEBUG
|
#ifdef _DEBUG
|
||||||
|
@ -158,6 +161,7 @@ bool AegisubApp::OnInit() {
|
||||||
// Local config, make ?user mean ?data so all user settings are placed in install dir
|
// Local config, make ?user mean ?data so all user settings are placed in install dir
|
||||||
config::path->SetToken("?user", config::path->Decode("?data"));
|
config::path->SetToken("?user", config::path->Decode("?data"));
|
||||||
config::path->SetToken("?local", config::path->Decode("?data"));
|
config::path->SetToken("?local", config::path->Decode("?data"));
|
||||||
|
crash_writer::Initialize(config::path->Decode("?user"));
|
||||||
} catch (agi::fs::FileSystemError const&) {
|
} catch (agi::fs::FileSystemError const&) {
|
||||||
// File doesn't exist or we can't read it
|
// File doesn't exist or we can't read it
|
||||||
// Might be worth displaying an error in the second case
|
// Might be worth displaying an error in the second case
|
||||||
|
@ -306,49 +310,6 @@ int AegisubApp::OnExit() {
|
||||||
return wxApp::OnExit();
|
return wxApp::OnExit();
|
||||||
}
|
}
|
||||||
|
|
||||||
#if wxUSE_STACKWALKER == 1
|
|
||||||
class StackWalker: public wxStackWalker {
|
|
||||||
boost::filesystem::ofstream fp;
|
|
||||||
|
|
||||||
public:
|
|
||||||
StackWalker(std::string const& cause);
|
|
||||||
~StackWalker();
|
|
||||||
void OnStackFrame(wxStackFrame const& frame) override;
|
|
||||||
};
|
|
||||||
|
|
||||||
/// @brief Called at the start of walking the stack.
|
|
||||||
/// @param cause cause of the crash.
|
|
||||||
StackWalker::StackWalker(std::string const& cause)
|
|
||||||
: fp(config::path->Decode("?user/crashlog.txt"), std::ios::app)
|
|
||||||
{
|
|
||||||
if (!fp.good()) return;
|
|
||||||
|
|
||||||
fp << agi::util::strftime("--- %y-%m-%d %H:%M:%S ------------------\n");
|
|
||||||
fp << boost::format("VER - %s\n") % GetAegisubLongVersionString();
|
|
||||||
fp << boost::format("FTL - Beginning stack dump for \"%s\": \n") % cause;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @brief Callback to format a single frame
|
|
||||||
/// @param frame frame to parse.
|
|
||||||
void StackWalker::OnStackFrame(wxStackFrame const& frame) {
|
|
||||||
if (!fp.good()) return;
|
|
||||||
|
|
||||||
fp << boost::format("%03u - %p: %s") % frame.GetLevel() % frame.GetAddress() % frame.GetName().utf8_str().data();
|
|
||||||
if (frame.HasSourceLocation())
|
|
||||||
fp << boost::format(" on %s:%u") % frame.GetFileName().utf8_str().data() % frame.GetLine();
|
|
||||||
|
|
||||||
fp << "\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @brief Called at the end of walking the stack.
|
|
||||||
StackWalker::~StackWalker() {
|
|
||||||
if (!fp.good()) return;
|
|
||||||
|
|
||||||
fp << "End of stack dump.\n";
|
|
||||||
fp << "----------------------------------------\n\n";
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/// Message displayed when an exception has occurred.
|
/// Message displayed when an exception has occurred.
|
||||||
const static wxString exception_message = _("Oops, Aegisub has crashed!\n\nAn attempt has been made to save a copy of your file to:\n\n%s\n\nAegisub will now close.");
|
const static wxString exception_message = _("Oops, Aegisub has crashed!\n\nAn attempt has been made to save a copy of your file to:\n\n%s\n\nAegisub will now close.");
|
||||||
|
|
||||||
|
@ -363,23 +324,15 @@ static void UnhandledExeception(bool stackWalk, agi::Context *c) {
|
||||||
path /= filename;
|
path /= filename;
|
||||||
c->subsController->Save(path);
|
c->subsController->Save(path);
|
||||||
|
|
||||||
#if wxUSE_STACKWALKER == 1
|
if (stackWalk)
|
||||||
if (stackWalk) {
|
crash_writer::Write();
|
||||||
StackWalker walker("Fatal exception");
|
|
||||||
walker.WalkFromException();
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Inform user of crash.
|
// Inform user of crash.
|
||||||
wxMessageBox(wxString::Format(exception_message, path.wstring()), _("Program error"), wxOK | wxICON_ERROR | wxCENTER, nullptr);
|
wxMessageBox(wxString::Format(exception_message, path.wstring()), _("Program error"), wxOK | wxICON_ERROR | wxCENTER, nullptr);
|
||||||
}
|
}
|
||||||
else if (LastStartupState) {
|
else if (LastStartupState) {
|
||||||
#if wxUSE_STACKWALKER == 1
|
if (stackWalk)
|
||||||
if (stackWalk) {
|
crash_writer::Write();
|
||||||
StackWalker walker("Fatal exception");
|
|
||||||
walker.WalkFromException();
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
wxMessageBox(wxString::Format("Aegisub has crashed while starting up!\n\nThe last startup step attempted was: %s.", LastStartupState), _("Program error"), wxOK | wxICON_ERROR | wxCENTER);
|
wxMessageBox(wxString::Format("Aegisub has crashed while starting up!\n\nThe last startup step attempted was: %s.", LastStartupState), _("Program error"), wxOK | wxICON_ERROR | wxCENTER);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -444,15 +397,7 @@ int AegisubApp::OnRun() {
|
||||||
|
|
||||||
// Report errors
|
// Report errors
|
||||||
if (!error.empty()) {
|
if (!error.empty()) {
|
||||||
boost::filesystem::ofstream file(config::path->Decode("?user/crashlog.txt"), std::ios::app);
|
crash_writer::Write(error);
|
||||||
if (file.is_open()) {
|
|
||||||
file << agi::util::strftime("--- %y-%m-%d %H:%M:%S ------------------\n");
|
|
||||||
file << boost::format("VER - %s\n") % GetAegisubLongVersionString();
|
|
||||||
file << boost::format("EXC - Aegisub has crashed with unhandled exception \"%s\".\n") % error;
|
|
||||||
file << "----------------------------------------\n\n";
|
|
||||||
file.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
OnUnhandledException();
|
OnUnhandledException();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue