Fix crash_writer_minidump.cpp's newlines

This commit is contained in:
Thomas Goyne 2014-03-20 19:54:44 -07:00
parent 0c9f39ca25
commit df177ae869

View file

@ -1,153 +1,153 @@
// Copyright (c) 2014, Thomas Goyne <plorkyeran@aegisub.org> // Copyright (c) 2014, Thomas Goyne <plorkyeran@aegisub.org>
// //
// Permission to use, copy, modify, and distribute this software for any // Permission to use, copy, modify, and distribute this software for any
// purpose with or without fee is hereby granted, provided that the above // purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies. // copyright notice and this permission notice appear in all copies.
// //
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES // ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. // OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
// //
// Aegisub Project http://www.aegisub.org/ // Aegisub Project http://www.aegisub.org/
#include "config.h" #include "config.h"
#include "crash_writer.h" #include "crash_writer.h"
#include "version.h" #include "version.h"
#include <libaegisub/fs.h> #include <libaegisub/fs.h>
#include <libaegisub/util.h> #include <libaegisub/util.h>
#include <atomic> #include <atomic>
#include <boost/filesystem/fstream.hpp> #include <boost/filesystem/fstream.hpp>
#include <boost/format.hpp> #include <boost/format.hpp>
#include <condition_variable> #include <condition_variable>
#include <mutex> #include <mutex>
#include <thread> #include <thread>
#include <DbgHelp.h> #include <DbgHelp.h>
#include <Windows.h> #include <Windows.h>
extern EXCEPTION_POINTERS *wxGlobalSEInformation; extern EXCEPTION_POINTERS *wxGlobalSEInformation;
namespace { namespace {
wchar_t crash_dump_path[MAX_PATH]; wchar_t crash_dump_path[MAX_PATH];
agi::fs::path crashlog_path; agi::fs::path crashlog_path;
using MiniDumpWriteDump = BOOL(WINAPI *)( using MiniDumpWriteDump = BOOL(WINAPI *)(
HANDLE hProcess, HANDLE hProcess,
DWORD dwPid, DWORD dwPid,
HANDLE hFile, HANDLE hFile,
MINIDUMP_TYPE DumpType, MINIDUMP_TYPE DumpType,
CONST PMINIDUMP_EXCEPTION_INFORMATION ExceptionParam, CONST PMINIDUMP_EXCEPTION_INFORMATION ExceptionParam,
CONST PMINIDUMP_USER_STREAM_INFORMATION UserStreamParam, CONST PMINIDUMP_USER_STREAM_INFORMATION UserStreamParam,
CONST PMINIDUMP_CALLBACK_INFORMATION CallbackParam); CONST PMINIDUMP_CALLBACK_INFORMATION CallbackParam);
struct dump_thread_state { struct dump_thread_state {
std::mutex start_mutex; std::mutex start_mutex;
std::condition_variable start_cv; std::condition_variable start_cv;
std::atomic<bool> exit = false; std::atomic<bool> exit = false;
EXCEPTION_POINTERS *ep = nullptr; EXCEPTION_POINTERS *ep = nullptr;
DWORD thread_id = 0; DWORD thread_id = 0;
// Must be last so everything else is initialized before it // Must be last so everything else is initialized before it
std::thread thread; std::thread thread;
dump_thread_state() : thread([&] { main(); }) { } dump_thread_state() : thread([&] { main(); }) { }
void main() { void main() {
auto module = LoadLibrary(L"dbghelp.dll"); auto module = LoadLibrary(L"dbghelp.dll");
if (!module) return; if (!module) return;
auto fn = reinterpret_cast<MiniDumpWriteDump>(GetProcAddress(module, "MiniDumpWriteDump")); auto fn = reinterpret_cast<MiniDumpWriteDump>(GetProcAddress(module, "MiniDumpWriteDump"));
if (!fn) { if (!fn) {
FreeLibrary(module); FreeLibrary(module);
return; return;
} }
std::unique_lock<std::mutex> lock(start_mutex); std::unique_lock<std::mutex> lock(start_mutex);
start_cv.wait(lock, [&] { return ep || exit; }); start_cv.wait(lock, [&] { return ep || exit; });
if (ep) if (ep)
write_dump(fn); write_dump(fn);
FreeLibrary(module); FreeLibrary(module);
} }
void write_dump(MiniDumpWriteDump fn) { void write_dump(MiniDumpWriteDump fn) {
auto file = CreateFile(crash_dump_path, auto file = CreateFile(crash_dump_path,
GENERIC_WRITE, GENERIC_WRITE,
0, // no sharing 0, // no sharing
nullptr, nullptr,
CREATE_NEW, CREATE_NEW,
FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_NORMAL,
nullptr); nullptr);
if (file == INVALID_HANDLE_VALUE) return; if (file == INVALID_HANDLE_VALUE) return;
MINIDUMP_EXCEPTION_INFORMATION info; MINIDUMP_EXCEPTION_INFORMATION info;
info.ThreadId = thread_id; info.ThreadId = thread_id;
info.ExceptionPointers = ep; info.ExceptionPointers = ep;
info.ClientPointers = FALSE; info.ClientPointers = FALSE;
fn(GetCurrentProcess(), GetCurrentProcessId(), file, MiniDumpNormal, &info, nullptr, nullptr); fn(GetCurrentProcess(), GetCurrentProcessId(), file, MiniDumpNormal, &info, nullptr, nullptr);
CloseHandle(file); CloseHandle(file);
} }
}; };
std::unique_ptr<dump_thread_state> dump_thread; std::unique_ptr<dump_thread_state> dump_thread;
} }
namespace crash_writer { namespace crash_writer {
void Initialize(agi::fs::path const& path) { void Initialize(agi::fs::path const& path) {
crashlog_path = path / "crashlog.txt"; crashlog_path = path / "crashlog.txt";
auto dump_path = path / "crashdumps"; auto dump_path = path / "crashdumps";
agi::fs::CreateDirectory(dump_path); agi::fs::CreateDirectory(dump_path);
const auto path_str = (dump_path / GetVersionNumber()).wstring(); const auto path_str = (dump_path / GetVersionNumber()).wstring();
wcscpy_s(crash_dump_path, path_str.c_str()); wcscpy_s(crash_dump_path, path_str.c_str());
auto len = path_str.size(); auto len = path_str.size();
const auto t = time(nullptr); const auto t = time(nullptr);
struct tm tm; struct tm tm;
localtime_s(&tm, &t); localtime_s(&tm, &t);
len += wcsftime(crash_dump_path + len, MAX_PATH - len, L"-%Y-%m-%d-%H-%M-%S-", &tm); len += wcsftime(crash_dump_path + len, MAX_PATH - len, L"-%Y-%m-%d-%H-%M-%S-", &tm);
len += swprintf_s(crash_dump_path + len, MAX_PATH - len, L"%d", GetCurrentProcessId()); len += swprintf_s(crash_dump_path + len, MAX_PATH - len, L"%d", GetCurrentProcessId());
wcscpy_s(crash_dump_path + len, MAX_PATH - len, L".dmp"); wcscpy_s(crash_dump_path + len, MAX_PATH - len, L".dmp");
if (!dump_thread) if (!dump_thread)
dump_thread = agi::util::make_unique<dump_thread_state>(); dump_thread = agi::util::make_unique<dump_thread_state>();
} }
void Cleanup() { void Cleanup() {
dump_thread->exit = true; dump_thread->exit = true;
dump_thread->start_cv.notify_all(); dump_thread->start_cv.notify_all();
dump_thread->thread.join(); dump_thread->thread.join();
dump_thread.reset(); dump_thread.reset();
} }
void Write() { void Write() {
dump_thread->ep = wxGlobalSEInformation; dump_thread->ep = wxGlobalSEInformation;
dump_thread->thread_id = GetCurrentThreadId(); dump_thread->thread_id = GetCurrentThreadId();
dump_thread->start_cv.notify_all(); dump_thread->start_cv.notify_all();
dump_thread->thread.join(); dump_thread->thread.join();
dump_thread.reset(); dump_thread.reset();
} }
void Write(std::string const& error) { void Write(std::string const& error) {
boost::filesystem::ofstream file(crashlog_path, std::ios::app); boost::filesystem::ofstream file(crashlog_path, std::ios::app);
if (file.is_open()) { if (file.is_open()) {
file << agi::util::strftime("--- %y-%m-%d %H:%M:%S ------------------\n"); file << agi::util::strftime("--- %y-%m-%d %H:%M:%S ------------------\n");
file << boost::format("VER - %s\n") % GetAegisubLongVersionString(); file << boost::format("VER - %s\n") % GetAegisubLongVersionString();
file << boost::format("EXC - Aegisub has crashed with unhandled exception \"%s\".\n") % error; file << boost::format("EXC - Aegisub has crashed with unhandled exception \"%s\".\n") % error;
file << "----------------------------------------\n\n"; file << "----------------------------------------\n\n";
file.close(); file.close();
} }
} }
} }