diff --git a/CHANGELOG.md b/CHANGELOG.md index 8017a253f..37bb8d7b1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -69,6 +69,7 @@ Feature #4404: Editor: All EnumDelegate fields should have their items sorted alphabetically Feature #4444: Per-group KF-animation files support Feature #4466: Editor: Add option to ignore "Base" records when running verifier + Feature #4012: Editor: Write a log file if OpenCS crashes 0.44.0 ------ diff --git a/apps/opencs/editor.cpp b/apps/opencs/editor.cpp index 35ce51337..6ca10e0f6 100644 --- a/apps/opencs/editor.cpp +++ b/apps/opencs/editor.cpp @@ -5,6 +5,9 @@ #include #include + +#include + #include #include @@ -18,12 +21,16 @@ using namespace Fallback; -CS::Editor::Editor () +CS::Editor::Editor (int argc, char **argv) : mSettingsState (mCfgMgr), mDocumentManager (mCfgMgr), mViewManager (mDocumentManager), mPid(""), mLock(), mMerge (mDocumentManager), mIpcServerName ("org.openmw.OpenCS"), mServer(NULL), mClientSocket(NULL) -{ +{ + // install the crash handler as soon as possible. note that the log path + // does not depend on config being read. + crashCatcherInstall(argc, argv, (mCfgMgr.getLogPath() / "openmw-cs-crash.log").string()); + std::pair > config = readConfig(); setupDataFiles (config.first); diff --git a/apps/opencs/editor.hpp b/apps/opencs/editor.hpp index b60f5c6a8..21199e2ca 100644 --- a/apps/opencs/editor.hpp +++ b/apps/opencs/editor.hpp @@ -66,7 +66,7 @@ namespace CS public: - Editor (); + Editor (int argc, char **argv); ~Editor (); bool makeIPCServer(); diff --git a/apps/opencs/main.cpp b/apps/opencs/main.cpp index fc5e8fc7a..d599f1f96 100644 --- a/apps/opencs/main.cpp +++ b/apps/opencs/main.cpp @@ -48,7 +48,7 @@ int main(int argc, char *argv[]) #endif try - { + { // To allow background thread drawing in OSG QApplication::setAttribute(Qt::AA_X11InitThreads, true); @@ -67,7 +67,7 @@ int main(int argc, char *argv[]) application.setWindowIcon (QIcon (":./openmw-cs.png")); - CS::Editor editor; + CS::Editor editor(argc, argv); if(!editor.makeIPCServer()) { diff --git a/apps/openmw/CMakeLists.txt b/apps/openmw/CMakeLists.txt index e64998077..e8a958d45 100644 --- a/apps/openmw/CMakeLists.txt +++ b/apps/openmw/CMakeLists.txt @@ -11,12 +11,10 @@ if (ANDROID) set(GAME ${GAME} android_main.c) endif() -if(NOT WIN32 AND NOT ANDROID) - set(GAME ${GAME} crashcatcher.cpp) -endif() set(GAME_HEADER engine.hpp ) + source_group(game FILES ${GAME} ${GAME_HEADER}) add_openmw_dir (mwrender diff --git a/apps/openmw/main.cpp b/apps/openmw/main.cpp index 109610b1e..d13a73127 100644 --- a/apps/openmw/main.cpp +++ b/apps/openmw/main.cpp @@ -1,6 +1,7 @@ #include #include +#include #include #include #include @@ -24,18 +25,6 @@ #include #endif -#if (defined(__APPLE__) || (defined(__linux) && !defined(ANDROID)) || (defined(__unix) && !defined(ANDROID)) || defined(__posix)) - #define USE_CRASH_CATCHER 1 -#else - #define USE_CRASH_CATCHER 0 -#endif - -#if USE_CRASH_CATCHER -#include -extern int cc_install_handlers(int argc, char **argv, int num_signals, int *sigs, const char *logfile, int (*user_info)(char*, char*)); -extern int is_debugger_attached(void); -#endif - /** * Workaround for problems with whitespaces in paths in older versions of Boost library */ @@ -339,18 +328,7 @@ int main(int argc, char**argv) std::cerr.rdbuf (&cerrsb); #endif - -#if USE_CRASH_CATCHER - // Unix crash catcher - if ((argc == 2 && strcmp(argv[1], "--cc-handle-crash") == 0) || !is_debugger_attached()) - { - int s[5] = { SIGSEGV, SIGILL, SIGFPE, SIGBUS, SIGABRT }; - cc_install_handlers(argc, argv, 5, s, (cfgMgr.getLogPath() / "crash.log").string().c_str(), NULL); - std::cout << "Installing crash catcher" << std::endl; - } - else - std::cout << "Running in a debugger, not installing crash catcher" << std::endl; -#endif + crashCatcherInstall(argc, argv, (cfgMgr.getLogPath() / "crash.log").string()); #ifdef __APPLE__ boost::filesystem::path binary_path = boost::filesystem::system_complete(boost::filesystem::path(argv[0])); diff --git a/cmake/OpenMWMacros.cmake b/cmake/OpenMWMacros.cmake index 2fa86094f..f385437b4 100644 --- a/cmake/OpenMWMacros.cmake +++ b/cmake/OpenMWMacros.cmake @@ -204,4 +204,4 @@ macro (copy_all_resource_files source_dir destination_dir_base destination_dir_r get_filename_component(filename ${f} NAME) copy_resource_file("${source_dir}/${f}" "${destination_dir_base}" "${destination_dir_relative}/${filename}") endforeach (f) -endmacro (copy_all_resource_files) \ No newline at end of file +endmacro (copy_all_resource_files) diff --git a/components/CMakeLists.txt b/components/CMakeLists.txt index 3efd236cb..b6f390b06 100644 --- a/components/CMakeLists.txt +++ b/components/CMakeLists.txt @@ -145,6 +145,12 @@ add_component_dir (fallback fallback validate ) +if(NOT WIN32 AND NOT ANDROID) + add_component_dir (crashcatcher + crashcatcher + ) +endif() + set (ESM_UI ${CMAKE_SOURCE_DIR}/files/ui/contentselector.ui ) diff --git a/apps/openmw/crashcatcher.cpp b/components/crashcatcher/crashcatcher.cpp similarity index 91% rename from apps/openmw/crashcatcher.cpp rename to components/crashcatcher/crashcatcher.cpp index 0078ef169..af42eb695 100644 --- a/apps/openmw/crashcatcher.cpp +++ b/components/crashcatcher/crashcatcher.cpp @@ -14,7 +14,11 @@ #include #include -#include +#include + +#include + +namespace bfs = boost::filesystem; #include @@ -402,7 +406,7 @@ static void crash_handler(const char *logfile) exit(0); } -int cc_install_handlers(int argc, char **argv, int num_signals, int *signals, const char *logfile, int (*user_info)(char*, char*)) +int crashCatcherInstallHandlers(int argc, char **argv, int num_signals, int *signals, const char *logfile, int (*user_info)(char*, char*)) { struct sigaction sa; stack_t altss; @@ -454,19 +458,31 @@ int cc_install_handlers(int argc, char **argv, int num_signals, int *signals, co return retval; } - -// gdb apparently opens FD(s) 3,4,5 (whereas a typical prog uses only stdin=0, stdout=1,stderr=2) -bool -is_debugger_attached(void) +static bool is_debugger_present() { - bool rc = false; - FILE *fd = fopen("/tmp", "r"); - - if (fileno(fd) > 5) + bfs::ifstream file((bfs::path("/proc/self/status"))); + while (!file.eof()) { - rc = true; + std::string word; + file >> word; + if (word == "TracerPid:") + { + file >> word; + return word != "0"; + } } + return false; +} - fclose(fd); - return rc; +void crashCatcherInstall(int argc, char **argv, const std::string &crashLogPath) +{ + if ((argc == 2 && strcmp(argv[1], "--cc-handle-crash") == 0) || !is_debugger_present()) + { + int s[5] = { SIGSEGV, SIGILL, SIGFPE, SIGBUS, SIGABRT }; + if (crashCatcherInstallHandlers(argc, argv, 5, s, crashLogPath.c_str(), NULL) == -1) + { + std::cerr << "Installing crash handler failed" << std::endl; + } else + std::cout << "Crash handler installed" << std::endl; + } } diff --git a/components/crashcatcher/crashcatcher.hpp b/components/crashcatcher/crashcatcher.hpp new file mode 100644 index 000000000..e2390df9c --- /dev/null +++ b/components/crashcatcher/crashcatcher.hpp @@ -0,0 +1,18 @@ +#ifndef CRASHCATCHER_H +#define CRASHCATCHER_H + +#include + +#if (defined(__APPLE__) || (defined(__linux) && !defined(ANDROID)) || (defined(__unix) && !defined(ANDROID)) || defined(__posix)) + #define USE_CRASH_CATCHER 1 +#else + #define USE_CRASH_CATCHER 0 +#endif + +#if USE_CRASH_CATCHER +extern void crashCatcherInstall(int argc, char **argv, const std::string &crashLogPath); +#else +inline void crashCatcherInstall(int, char **, const std::string &crashLogPath) { return 0; } +#endif + +#endif