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)compat.h" />
|
||||
<ClInclude Include="$(SrcDir)config.h" />
|
||||
<ClInclude Include="$(SrcDir)crash_writer.h" />
|
||||
<ClInclude Include="$(SrcDir)dialog_about.h" />
|
||||
<ClInclude Include="$(SrcDir)dialog_attachments.h" />
|
||||
<ClInclude Include="$(SrcDir)dialog_automation.h" />
|
||||
|
@ -347,6 +348,7 @@
|
|||
<ClCompile Include="$(SrcDir)command\video.cpp" />
|
||||
<ClCompile Include="$(SrcDir)command\vis_tool.cpp" />
|
||||
<ClCompile Include="$(SrcDir)compat.cpp" />
|
||||
<ClCompile Include="$(SrcDir)crash_writer.cpp" />
|
||||
<ClCompile Include="$(SrcDir)dialog_about.cpp" />
|
||||
<ClCompile Include="$(SrcDir)dialog_attachments.cpp" />
|
||||
<ClCompile Include="$(SrcDir)dialog_automation.cpp" />
|
||||
|
|
|
@ -594,6 +594,9 @@
|
|||
<ClInclude Include="$(SrcDir)dialog_log.h">
|
||||
<Filter>Utilities\Logging</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="$(SrcDir)crash_writer.h">
|
||||
<Filter>Utilities\Logging</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="$(SrcDir)utils.h">
|
||||
<Filter>Utilities</Filter>
|
||||
</ClInclude>
|
||||
|
@ -1232,6 +1235,9 @@
|
|||
<ClCompile Include="$(SrcDir)resolution_resampler.cpp">
|
||||
<Filter>Features\Resolution resampler</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="$(SrcDir)crash_writer.cpp">
|
||||
<Filter>Utilities\Logging</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ResourceCompile Include="$(SrcDir)res/res.rc">
|
||||
|
|
|
@ -154,6 +154,7 @@ SRC += \
|
|||
colorspace.cpp \
|
||||
colour_button.cpp \
|
||||
compat.cpp \
|
||||
crash_writer.cpp \
|
||||
dialog_about.cpp \
|
||||
dialog_attachments.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 "main.h"
|
||||
|
||||
#include "command/command.h"
|
||||
#include "include/aegisub/hotkey.h"
|
||||
|
||||
|
@ -41,18 +43,18 @@
|
|||
#include "ass_file.h"
|
||||
#include "auto4_base.h"
|
||||
#include "compat.h"
|
||||
#include "crash_writer.h"
|
||||
#include "export_fixstyle.h"
|
||||
#include "export_framerate.h"
|
||||
#include "frame_main.h"
|
||||
#include "include/aegisub/context.h"
|
||||
#include "main.h"
|
||||
#include "libresrc/libresrc.h"
|
||||
#include "options.h"
|
||||
#include "plugin_manager.h"
|
||||
#include "subs_controller.h"
|
||||
#include "subtitle_format.h"
|
||||
#include "version.h"
|
||||
#include "video_context.h"
|
||||
#include "version.h"
|
||||
#include "utils.h"
|
||||
|
||||
#include <libaegisub/dispatch.h>
|
||||
|
@ -140,6 +142,7 @@ bool AegisubApp::OnInit() {
|
|||
});
|
||||
|
||||
config::path = new agi::Path;
|
||||
crash_writer::Initialize(config::path->Decode("?user"));
|
||||
|
||||
agi::log::log = new agi::log::LogSink;
|
||||
#ifdef _DEBUG
|
||||
|
@ -158,6 +161,7 @@ bool AegisubApp::OnInit() {
|
|||
// 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("?local", config::path->Decode("?data"));
|
||||
crash_writer::Initialize(config::path->Decode("?user"));
|
||||
} catch (agi::fs::FileSystemError const&) {
|
||||
// File doesn't exist or we can't read it
|
||||
// Might be worth displaying an error in the second case
|
||||
|
@ -306,49 +310,6 @@ int AegisubApp::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.
|
||||
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;
|
||||
c->subsController->Save(path);
|
||||
|
||||
#if wxUSE_STACKWALKER == 1
|
||||
if (stackWalk) {
|
||||
StackWalker walker("Fatal exception");
|
||||
walker.WalkFromException();
|
||||
}
|
||||
#endif
|
||||
if (stackWalk)
|
||||
crash_writer::Write();
|
||||
|
||||
// Inform user of crash.
|
||||
wxMessageBox(wxString::Format(exception_message, path.wstring()), _("Program error"), wxOK | wxICON_ERROR | wxCENTER, nullptr);
|
||||
}
|
||||
else if (LastStartupState) {
|
||||
#if wxUSE_STACKWALKER == 1
|
||||
if (stackWalk) {
|
||||
StackWalker walker("Fatal exception");
|
||||
walker.WalkFromException();
|
||||
}
|
||||
#endif
|
||||
if (stackWalk)
|
||||
crash_writer::Write();
|
||||
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
|
||||
|
@ -444,15 +397,7 @@ int AegisubApp::OnRun() {
|
|||
|
||||
// Report errors
|
||||
if (!error.empty()) {
|
||||
boost::filesystem::ofstream file(config::path->Decode("?user/crashlog.txt"), std::ios::app);
|
||||
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();
|
||||
}
|
||||
|
||||
crash_writer::Write(error);
|
||||
OnUnhandledException();
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue