Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

#1653: Create a log file and add it to crash report. #1657

Merged
merged 3 commits into from
Jan 17, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
62 changes: 62 additions & 0 deletions common/src/FileLogger.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
/*
Copyright (C) 2010-2016 Kristian Duske

This file is part of TrenchBroom.

TrenchBroom is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

TrenchBroom is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with TrenchBroom. If not, see <http://www.gnu.org/licenses/>.
*/

#include "FileLogger.h"

#include "Ensure.h"
#include "IO/DiskIO.h"
#include "IO/Path.h"
#include "IO/SystemPaths.h"

#include <cassert>

#include <wx/string.h>

namespace TrenchBroom {
FileLogger::FileLogger(const IO::Path& filePath) :
m_file(NULL) {
IO::Disk::ensureDirectoryExists(filePath.deleteLastComponent());
m_file = fopen(filePath.asString().c_str(), "w");
ensure(m_file != NULL, "log file could not be opened");
}

FileLogger::~FileLogger() {
if (m_file != NULL) {
fclose(m_file);
m_file = NULL;
}
}

FileLogger& FileLogger::instance() {
static FileLogger Instance(IO::SystemPaths::logFilePath());
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't see where the parent directory of IO::SystemPaths::logFilePath() is created, is that a potential problem?

Testing on macOS, I tried deleting ~/Library/Application Support/TrenchBroom and then launching TB, and the TrenchBroom directory was created and everything worked.

return Instance;
}

void FileLogger::doLog(const LogLevel level, const String& message) {
assert(m_file != NULL);
if (m_file != NULL) {
std::fprintf(m_file, "%s\n", message.c_str());
std::fflush(m_file);
}
}

void FileLogger::doLog(const LogLevel level, const wxString& message) {
log(level, message.ToStdString());
}
}
46 changes: 46 additions & 0 deletions common/src/FileLogger.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
/*
Copyright (C) 2010-2016 Kristian Duske

This file is part of TrenchBroom.

TrenchBroom is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

TrenchBroom is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with TrenchBroom. If not, see <http://www.gnu.org/licenses/>.
*/

#ifndef FileLogger_h
#define FileLogger_h

#include "Logger.h"

#include <cstdio>

namespace TrenchBroom {
namespace IO {
class Path;
}

class FileLogger : public Logger {
private:
FILE* m_file;
public:
FileLogger(const IO::Path& filePath);
~FileLogger();

static FileLogger& instance();
private:
void doLog(LogLevel level, const String& message) override;
void doLog(LogLevel level, const wxString& message) override;
};
}

#endif /* FileLogger_h */
8 changes: 8 additions & 0 deletions common/src/IO/DiskIO.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,14 @@ namespace TrenchBroom {
return ::wxMkdir(path.asString());
}

void ensureDirectoryExists(const Path& path) {
const Path fixedPath = fixPath(path);
if (fileExists(fixedPath))
throw FileSystemException("Could not create directory '" + fixedPath.asString() + "': A file already exists at that path.");
if (!directoryExists(fixedPath))
createDirectoryHelper(fixedPath);
}

void deleteFile(const Path& path) {
const Path fixedPath = fixPath(path);
if (!fileExists(fixedPath))
Expand Down
1 change: 1 addition & 0 deletions common/src/IO/DiskIO.h
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ namespace TrenchBroom {

void createFile(const Path& path, const String& contents);
void createDirectory(const Path& path);
void ensureDirectoryExists(const Path& path);
void deleteFile(const Path& path);

template <typename M>
Expand Down
6 changes: 5 additions & 1 deletion common/src/IO/SystemPaths.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ namespace TrenchBroom {
Path appDirectory() {
return IO::Path(wxStandardPaths::Get().GetExecutablePath().ToStdString()).deleteLastComponent();
}

#if defined __linux__
static bool getDevMode() {
wxString value;
Expand All @@ -53,6 +53,10 @@ namespace TrenchBroom {
Path userDataDirectory() {
return IO::Path(wxStandardPaths::Get().GetUserDataDir().ToStdString());
}

Path logFilePath() {
return userDataDirectory() + IO::Path("TrenchBroom.log");
}
}
}
}
Expand Down
3 changes: 2 additions & 1 deletion common/src/IO/SystemPaths.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,10 @@ namespace TrenchBroom {

namespace SystemPaths {
Path appDirectory();
Path logDirectory();
Path resourceDirectory();
Path userDataDirectory();

Path logFilePath();
}
}
}
Expand Down
46 changes: 33 additions & 13 deletions common/src/TrenchBroomApp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,7 @@ namespace TrenchBroom {
Bind(wxEVT_MENU, &TrenchBroomApp::OnHelpShowManual, this, wxID_HELP);
Bind(wxEVT_MENU, &TrenchBroomApp::OnOpenPreferences, this, wxID_PREFERENCES);
Bind(wxEVT_MENU, &TrenchBroomApp::OnOpenAbout, this, wxID_ABOUT);
Bind(wxEVT_MENU, &TrenchBroomApp::OnDebugShowCrashReportDialog, this, CommandIds::Menu::DebugCrashReportDialog);

Bind(EXECUTABLE_EVENT, &TrenchBroomApp::OnExecutableEvent, this);

Expand Down Expand Up @@ -313,7 +314,7 @@ namespace TrenchBroom {
return mapPath;
}

static IO::Path crashLogPath() {
static IO::Path crashReportBasePath() {
IO::Path mapPath = savedMapPath();
IO::Path crashLogPath;

Expand All @@ -336,7 +337,7 @@ namespace TrenchBroom {

testCrashLogPath = crashLogPath.deleteLastComponent() + testCrashLogName.str();
}
return testCrashLogPath.asString();
return testCrashLogPath.deleteExtension().asString();
}

static bool inReportCrashAndExit = false;
Expand All @@ -348,39 +349,45 @@ namespace TrenchBroom {

void reportCrashAndExit(const String &stacktrace, const String &reason) {
// just abort if we reenter reportCrashAndExit (i.e. if it crashes)
if (inReportCrashAndExit) {
if (inReportCrashAndExit)
wxAbort();
}

inReportCrashAndExit = true;

// get the crash report as a string
String report = makeCrashReport(stacktrace, reason);
const String report = makeCrashReport(stacktrace, reason);

// write it to the crash log file
IO::Path logPath = crashLogPath();
IO::Path mapPath = logPath.deleteExtension().addExtension("map");
const IO::Path basePath = crashReportBasePath();
IO::Path reportPath = basePath.addExtension("txt");
IO::Path mapPath = basePath.addExtension("map");
IO::Path logPath = basePath.addExtension("log");

std::ofstream logStream(logPath.asString().c_str());
logStream << report;
logStream.close();
std::cerr << "wrote crash log to " << logPath.asString() << std::endl;
std::ofstream reportStream(reportPath.asString().c_str());
reportStream << report;
reportStream.close();
std::cerr << "wrote crash log to " << reportPath.asString() << std::endl;

// save the map
MapDocumentSPtr doc = topDocument();
if (doc) {
if (doc.get() != nullptr) {
doc->saveDocumentTo(mapPath);
std::cerr << "wrote map to " << mapPath.asString() << std::endl;
} else {
mapPath = IO::Path();
}

// Copy the log file
if (!wxCopyFile(IO::SystemPaths::logFilePath().asString(), logPath.asString()))
logPath = IO::Path();

// write the crash log to stdout
std::cerr << "crash log:" << std::endl;
std::cerr << report << std::endl;

if (crashReportGuiEnabled) {
CrashDialog dialog;
dialog.Create(logPath, mapPath);
dialog.Create(reportPath, mapPath, logPath);
dialog.ShowModal();
}

Expand Down Expand Up @@ -471,6 +478,16 @@ namespace TrenchBroom {
openAbout();
}

void TrenchBroomApp::OnDebugShowCrashReportDialog(wxCommandEvent& event) {
const IO::Path reportPath(IO::SystemPaths::userDataDirectory() + IO::Path("crashreport.txt"));
const IO::Path mapPath(IO::SystemPaths::userDataDirectory() + IO::Path("crashreport.map"));
const IO::Path logPath(IO::SystemPaths::userDataDirectory() + IO::Path("crashreport.log"));

CrashDialog dialog;
dialog.Create(reportPath, mapPath, logPath);
dialog.ShowModal();
}

void TrenchBroomApp::OnExecutableEvent(ExecutableEvent& event) {
event.execute();
}
Expand Down Expand Up @@ -509,6 +526,9 @@ namespace TrenchBroom {
case CommandIds::Menu::FileOpenRecent:
event.Enable(true);
break;
case CommandIds::Menu::DebugCrashReportDialog:
event.Enable(true);
break;
default:
if (event.GetId() >= CommandIds::Menu::FileRecentDocuments &&
event.GetId() < CommandIds::Menu::FileRecentDocuments + 10)
Expand Down
2 changes: 2 additions & 0 deletions common/src/TrenchBroomApp.h
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,8 @@ namespace TrenchBroom {
void OnHelpShowManual(wxCommandEvent& event);
void OnOpenPreferences(wxCommandEvent& event);
void OnOpenAbout(wxCommandEvent& event);
void OnDebugShowCrashReportDialog(wxCommandEvent& event);

void OnExecutableEvent(ExecutableEvent& event);

int FilterEvent(wxEvent& event);
Expand Down
1 change: 1 addition & 0 deletions common/src/View/ActionManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -280,6 +280,7 @@ namespace TrenchBroom {
debugMenu->addUnmodifiableActionItem(CommandIds::Menu::DebugClipWithFace, "Clip Brush...");
debugMenu->addUnmodifiableActionItem(CommandIds::Menu::DebugCopyJSShortcuts, "Copy Javascript Shortcut Map");
debugMenu->addUnmodifiableActionItem(CommandIds::Menu::DebugCrash, "Crash...");
debugMenu->addUnmodifiableActionItem(CommandIds::Menu::DebugCrashReportDialog, "Show Crash Report Dialog");
#endif

Menu* helpMenu = m_menuBar->addMenu("Help");
Expand Down
1 change: 1 addition & 0 deletions common/src/View/CommandIds.h
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ namespace TrenchBroom {
const int DebugCrash = Lowest + 130;
const int DebugCreateCube = Lowest + 131;
const int DebugClipWithFace = Lowest + 132;
const int DebugCrashReportDialog = Lowest + 133;

const int RunCompile = Lowest + 133;
const int RunLaunch = Lowest + 134;
Expand Down
3 changes: 2 additions & 1 deletion common/src/View/Console.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@

#include "Console.h"

#include "FileLogger.h"
#include "View/ViewConstants.h"

#include <wx/log.h>
Expand Down Expand Up @@ -49,7 +50,7 @@ namespace TrenchBroom {
if (!message.empty()) {
logToDebugOut(level, message);
logToConsole(level, message);
logNotifier(level, message);
FileLogger::instance().log(level, message);
}
}

Expand Down
2 changes: 0 additions & 2 deletions common/src/View/Console.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,6 @@ class wxTextCtrl;
namespace TrenchBroom {
namespace View {
class Console : public TabBookPage, public Logger {
public:
Notifier2<LogLevel, const wxString&> logNotifier;
private:
wxTextCtrl* m_textView;
public:
Expand Down