Merge pull request #1187 from manongjohn/replace_3rd_party_crashrpt
Replace 3rd party crashrpt
This commit is contained in:
commit
017754a47c
17 changed files with 717 additions and 164 deletions
8
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
8
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
|
@ -26,12 +26,7 @@ body:
|
|||
id: logs
|
||||
attributes:
|
||||
label: Relevant logs/screenshots
|
||||
description: If available, please provide relevant logs or screenshots.
|
||||
placeholder: |
|
||||
Crash logs or dmp files may be found under the following:
|
||||
Windows: crash dmp file - C:\Users\yourusername\AppData\Local\Tahoma2D\Tahoma2D\cache\crashrpt\xxxx\crashdump.dmp
|
||||
crash logs - Event Viewer -> Windows Logs -> Application. Look for Tahoma2D crash report
|
||||
macOS: crash logs - Console App -> User Reports. Look for Tahoma2D crash report
|
||||
description: If available, please provide relevant logs, screenshots or short videos. Windows users can add zipped crash dmp files.
|
||||
validations:
|
||||
required: false
|
||||
- type: markdown
|
||||
|
@ -45,6 +40,7 @@ body:
|
|||
label: Software Version
|
||||
description: What version of the software are you running?
|
||||
options:
|
||||
- 1.3.1
|
||||
- 1.3
|
||||
- Nightly (Specify below)
|
||||
- 1.2
|
||||
|
|
8
.github/workflows/windows_build.yml
vendored
8
.github/workflows/windows_build.yml
vendored
|
@ -46,10 +46,6 @@ jobs:
|
|||
with:
|
||||
name: Tahoma2D-win
|
||||
path: artifact
|
||||
- uses: actions/upload-artifact@v1
|
||||
with:
|
||||
name: debug-symbols.zip
|
||||
path: toonz\build\debug-symbols.zip
|
||||
- name: Get Nightly Release Date
|
||||
if: ${{ github.repository_owner == 'tahoma2d' && github.event_name == 'push' && github.ref == 'refs/heads/master' }}
|
||||
run: |
|
||||
|
@ -74,7 +70,7 @@ jobs:
|
|||
with:
|
||||
allowUpdates: true
|
||||
artifactErrorsFailBuild: false
|
||||
artifacts: toonz\build\Tahoma2D-win.zip,toonz\build\debug-symbols.zip
|
||||
artifacts: toonz\build\Tahoma2D-win.zip
|
||||
artifactContentType: "raw"
|
||||
body: ${{ github.event.head_commit.message }}
|
||||
name: Latest Nightly ${{ env.NIGHTLYDATE }}
|
||||
|
@ -88,7 +84,7 @@ jobs:
|
|||
with:
|
||||
allowUpdates: true
|
||||
artifactErrorsFailBuild: false
|
||||
artifacts: toonz\build\Tahoma2D-win.zip,toonz\build\debug-symbols.zip
|
||||
artifacts: toonz\build\Tahoma2D-win.zip
|
||||
artifactContentType: "raw"
|
||||
body: ${{ github.event.head_commit.message }}
|
||||
name: ${{ env.NIGHTLYDATETIME }}
|
||||
|
|
|
@ -28,10 +28,7 @@ IF EXIST ..\..\thirdparty\canon\Header set WITH_CANON=Y
|
|||
set WITH_GPHOTO2=N
|
||||
IF EXIST ..\..\thirdparty\libgphoto2\include set WITH_GPHOTO2=Y
|
||||
|
||||
set WITH_CRASHRPT=N
|
||||
IF EXIST ..\..\thirdparty\crashrpt\include set WITH_CRASHRPT=Y
|
||||
|
||||
cmake ..\sources -G %MSVCVERSION% -Ax64 -DQT_PATH=%QT_PATH% -DBOOST_ROOT=%BOOST_ROOT% -DOpenCV_DIR=%OPENCV_DIR% -DWITH_CANON=%WITH_CANON% -DWITH_GPHOTO2=%WITH_GPHOTO2% -DWITH_CRASHRPT=%WITH_CRASHRPT%
|
||||
cmake ..\sources -G %MSVCVERSION% -Ax64 -DQT_PATH=%QT_PATH% -DBOOST_ROOT=%BOOST_ROOT% -DOpenCV_DIR=%OPENCV_DIR% -DWITH_CANON=%WITH_CANON% -DWITH_GPHOTO2=%WITH_GPHOTO2%
|
||||
|
||||
|
||||
IF EXIST C:\ProgramData\chocolatey\bin\cl.exe (
|
||||
|
|
|
@ -10,10 +10,6 @@ echo ">>> Copy and configure Tahoma2D installation"
|
|||
|
||||
copy /y RelWithDebInfo\*.* Tahoma2D
|
||||
|
||||
REM Remove PDB and ILK files
|
||||
del Tahoma2D\*.pdb
|
||||
del Tahoma2D\*.ilk
|
||||
|
||||
copy /Y ..\..\thirdparty\freeglut\bin\x64\freeglut.dll Tahoma2D
|
||||
copy /Y ..\..\thirdparty\glew\glew-1.9.0\bin\64bit\glew32.dll Tahoma2D
|
||||
copy /Y ..\..\thirdparty\libmypaint\dist\64\libiconv-2.dll Tahoma2D
|
||||
|
@ -36,11 +32,8 @@ IF EXIST ..\..\thirdparty\libgphoto2\include (
|
|||
xcopy /Y /E ..\..\thirdparty\libgphoto2\bin Tahoma2D
|
||||
)
|
||||
|
||||
IF EXIST ..\..\thirdparty\crashrpt\include (
|
||||
copy /Y ..\..\thirdparty\apps\crashrpt\CrashRpt1500.dll Tahoma2D
|
||||
copy /Y ..\..\thirdparty\apps\crashrpt\CrashSender1500.exe Tahoma2D
|
||||
copy /Y ..\..\thirdparty\apps\crashrpt\crashrpt_lang.ini Tahoma2D
|
||||
)
|
||||
REM Remove ILK files
|
||||
del Tahoma2D\*.ilk
|
||||
|
||||
echo ">>> Copying stuff to Tahoma2D\tahomastuff"
|
||||
|
||||
|
@ -80,14 +73,4 @@ echo ">>> Creating Tahoma2D Windows package"
|
|||
IF EXIST Tahoma2D-win.zip del Tahoma2D-win.zip
|
||||
7z a Tahoma2D-win.zip Tahoma2D
|
||||
|
||||
IF EXIST ..\..\..\tahoma2d_symbols (
|
||||
echo ">>> Saving debugging symbols"
|
||||
mkdir ..\..\..\tahoma2d_symbols\%date:~10,4%-%date:~4,2%-%date:~7,2%
|
||||
copy /y RelWithDebInfo\*.* ..\..\..\tahoma2d_symbols\%date:~10,4%-%date:~4,2%-%date:~7,2%
|
||||
) else (
|
||||
echo ">>> Creating debugging symbols package"
|
||||
IF EXIST debug-symbols.zip del debug-symbols.zip
|
||||
7z a debug-symbols.zip RelWithDebInfo\*.*
|
||||
)
|
||||
|
||||
cd ../..
|
||||
|
|
|
@ -5,17 +5,6 @@ IF NOT EXIST apps mkdir apps
|
|||
cd apps
|
||||
echo * > .gitignore
|
||||
|
||||
echo ">>> Getting CrashRpt"
|
||||
|
||||
IF EXIST crashrpt rmdir /S /Q crashrpt
|
||||
curl -fsSL -o crashrpt-tahoma2d-win_2019.zip https://github.com/tahoma2d/crashrpt2/releases/download/v1.5.0.0/crashrpt-tahoma2d-win_2019.zip
|
||||
7z x crashrpt-tahoma2d-win_2019.zip
|
||||
rename crashrpt-tahoma2d-win_2019 crashrpt
|
||||
IF EXIST ..\crashrpt\include rmdir /S /Q ..\crashrpt\include
|
||||
IF EXIST ..\crashrpt\CrashRpt1500.lib del ..\crashrpt\CrashRpt1500.lib
|
||||
move crashrpt\include ..\crashrpt
|
||||
move crashrpt\CrashRpt1500.lib ..\crashrpt
|
||||
|
||||
echo ">>> Getting FFmpeg"
|
||||
|
||||
IF EXIST ffmpeg rmdir /S /Q ffmpeg
|
||||
|
|
|
@ -1,28 +0,0 @@
|
|||
CrashRpt
|
||||
|
||||
Copyright (c) 2003, The CrashRpt Project Authors.
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
* Neither the name of the author nor the names of its contributors
|
||||
may be used to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
||||
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||
TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||||
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
|
||||
OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
2
thirdparty/crashrpt/.gitignore
vendored
2
thirdparty/crashrpt/.gitignore
vendored
|
@ -1,2 +0,0 @@
|
|||
include/*
|
||||
*.lib
|
10
thirdparty/crashrpt/copy_crashrpt.txt
vendored
10
thirdparty/crashrpt/copy_crashrpt.txt
vendored
|
@ -1,10 +0,0 @@
|
|||
For Windows Builds Only!
|
||||
|
||||
Copy the include folder from the CrashRpt source to here.
|
||||
Compile CrashRpt and copy the CrashRptXXXX.lib here also.
|
||||
|
||||
When releasing with CrashRpt, include:
|
||||
CrashRptXXXX.dll
|
||||
CrashSenderXXXX.exe
|
||||
crashrpt_lang.ini
|
||||
dbghelp.dll (optional)
|
|
@ -107,7 +107,6 @@ option(WITH_SYSTEM_SUPERLU "Use the system SuperLU library instead of 'thirdpary
|
|||
option(WITH_CANON "Build with Canon DSLR support - Requires Canon SDK" OFF)
|
||||
option(WITH_GPHOTO2 "Build with Libgphoto2" OFF)
|
||||
option(WITH_TRANSLATION "Generate translation projects as well" ON)
|
||||
option(WITH_CRASHRPT "Build CrashRpt support - Requires CrashRpt Library" OFF)
|
||||
option(WITH_WINTAB "(Windows only) Build with customized Qt with WinTab support. https://github.com/shun-iwasawa/qt5/releases/tag/v5.15.2_wintab" OFF)
|
||||
|
||||
# avoid using again
|
||||
|
@ -284,12 +283,6 @@ if(BUILD_ENV_MSVC)
|
|||
-DGLUT_NO_LIB_PRAGMA
|
||||
)
|
||||
|
||||
if(WITH_CRASHRPT)
|
||||
include_directories(
|
||||
${SDKROOT}/crashrpt/include
|
||||
)
|
||||
endif()
|
||||
|
||||
if(WITH_GPHOTO2)
|
||||
include_directories(
|
||||
${SDKROOT}/libgphoto2/include
|
||||
|
@ -399,10 +392,6 @@ if(BUILD_ENV_MSVC)
|
|||
set(MYPAINT_LIB_INCLUDE_DIRS ${SDKROOT}/libmypaint/dist/${PLATFORM}/include/libmypaint)
|
||||
set(MYPAINT_LIB_LDFLAGS ${SDKROOT}/libmypaint/dist/${PLATFORM}/libmypaint.lib)
|
||||
|
||||
if(WITH_CRASHRPT)
|
||||
set(CRASHRPT_LIB ${SDKROOT}/crashrpt/CrashRpt1500.lib)
|
||||
endif()
|
||||
|
||||
if(WITH_GPHOTO2)
|
||||
set(GPHOTO2_LIB ${SDKROOT}/libgphoto2/lib/libgphoto2.lib)
|
||||
set(GPHOTO2_PORT_LIB ${SDKROOT}/libgphoto2/lib/libgphoto2_port.lib)
|
||||
|
|
|
@ -18,13 +18,6 @@
|
|||
|
||||
#include <sstream>
|
||||
|
||||
class TStringConvertException final : public TException {
|
||||
std::string m_string;
|
||||
|
||||
public:
|
||||
TStringConvertException(const std::string str) : m_string(str) {}
|
||||
};
|
||||
|
||||
std::wstring to_wstring(std::string s) {
|
||||
#ifdef TNZCORE_LIGHT
|
||||
std::wstring ws;
|
||||
|
|
|
@ -44,6 +44,7 @@ DVAPI TFilePath getLibraryFolder();
|
|||
DVAPI TFilePath getPluginsFolder();
|
||||
DVAPI TFilePath getReslistPath(bool forCleanup);
|
||||
DVAPI TFilePath getCacheRootFolder();
|
||||
DVAPI TFilePath getCrashReportFolder();
|
||||
DVAPI TFilePath getProfileFolder();
|
||||
|
||||
DVAPI TFilePath getMyReslistPath(bool forCleanup);
|
||||
|
|
|
@ -316,6 +316,7 @@ if(BUILD_ENV_MSVC)
|
|||
winmm.lib
|
||||
opengl32.lib
|
||||
glu32.lib
|
||||
dbghelp.lib
|
||||
)
|
||||
elseif(BUILD_ENV_APPLE)
|
||||
find_library(AUDIOUNIT_LIB AudioUnit)
|
||||
|
@ -344,6 +345,7 @@ elseif(BUILD_ENV_UNIXLIKE)
|
|||
-lmpr
|
||||
-lwinmm
|
||||
-lpsapi
|
||||
-ldbghelp
|
||||
)
|
||||
endif()
|
||||
endif()
|
||||
|
|
|
@ -30,6 +30,7 @@ set(MOC_HEADERS
|
|||
commandbar.h
|
||||
commandbarpopup.h
|
||||
convertpopup.h
|
||||
crashhandler.h
|
||||
duplicatepopup.h
|
||||
dvdirtreeview.h
|
||||
dvitemview.h
|
||||
|
@ -251,6 +252,7 @@ set(SOURCES
|
|||
addfilmstripframespopup.cpp
|
||||
camerasettingspopup.cpp
|
||||
convertpopup.cpp
|
||||
crashhandler.cpp
|
||||
duplicatepopup.cpp
|
||||
dvdirtreeview.cpp
|
||||
filebrowserpopup.cpp
|
||||
|
@ -449,14 +451,6 @@ if (WITH_CANON)
|
|||
add_definitions(-DWITH_CANON)
|
||||
endif()
|
||||
|
||||
if (WITH_CRASHRPT)
|
||||
add_definitions(-DWITH_CRASHRPT)
|
||||
endif()
|
||||
|
||||
if (WITH_GPHOTO2)
|
||||
add_definitions(-DWITH_GPHOTO2)
|
||||
endif()
|
||||
|
||||
if (WITH_WINTAB AND BUILD_TARGET_WIN AND (PLATFORM EQUAL 64))
|
||||
add_definitions(-DWITH_WINTAB)
|
||||
endif()
|
||||
|
@ -483,10 +477,6 @@ if(BUILD_ENV_MSVC)
|
|||
set(EXTRA_LIBS ${EXTRA_LIBS} ${CANON_LIB})
|
||||
endif()
|
||||
|
||||
if(WITH_CRASHRPT)
|
||||
set(EXTRA_LIBS ${EXTRA_LIBS} ${CRASHRPT_LIB})
|
||||
endif()
|
||||
|
||||
if(WITH_GPHOTO2)
|
||||
set(EXTRA_LIBS ${EXTRA_LIBS} ${GPHOTO2_LIB} ${GPHOTO2_PORT_LIB} ${GPHOTO2_COMPAT_LIB})
|
||||
endif()
|
||||
|
|
647
toonz/sources/toonz/crashhandler.cpp
Normal file
647
toonz/sources/toonz/crashhandler.cpp
Normal file
|
@ -0,0 +1,647 @@
|
|||
#include "crashhandler.h"
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <signal.h>
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
#include <winbase.h>
|
||||
#include <dbghelp.h>
|
||||
#include <psapi.h>
|
||||
#else
|
||||
#include <execinfo.h>
|
||||
#include <signal.h>
|
||||
#include <unistd.h>
|
||||
#include <err.h>
|
||||
#include <regex>
|
||||
#endif
|
||||
|
||||
#include "tgl.h"
|
||||
#include "tapp.h"
|
||||
#include "tenv.h"
|
||||
#include "tconvert.h"
|
||||
#include "texception.h"
|
||||
#include "tfilepath_io.h"
|
||||
#include "toonz/toonzfolders.h"
|
||||
#include "toonz/tproject.h"
|
||||
#include "toonz/tscenehandle.h"
|
||||
#include "toonz/toonzscene.h"
|
||||
|
||||
#include <QOperatingSystemVersion>
|
||||
#include <QDesktopServices>
|
||||
#include <QApplication>
|
||||
#include <QClipboard>
|
||||
#include <QThread>
|
||||
#include <QMainWindow>
|
||||
#include <QMessageBox>
|
||||
#include <QCloseEvent>
|
||||
#include <QDialog>
|
||||
#include <QLayout>
|
||||
#include <QLabel>
|
||||
#include <QTextEdit>
|
||||
#include <QPushButton>
|
||||
|
||||
static QWidget *s_parentWindow = NULL;
|
||||
static bool s_reportProjInfo = false;
|
||||
#ifdef _WIN32
|
||||
static PEXCEPTION_POINTERS s_exceptionPtr = NULL;
|
||||
#endif
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
static const char *filenameOnly(const char *path) {
|
||||
for (int i = strlen(path); i >= 0; --i) {
|
||||
if (path[i] == '\\' || path[i] == '/') return path + i + 1;
|
||||
}
|
||||
return path;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
// Windows platform functions
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
#define HAS_MINIDUMP
|
||||
static bool generateMinidump(TFilePath dumpFile,
|
||||
PEXCEPTION_POINTERS exceptionInfo) {
|
||||
HANDLE hDumpFile = CreateFileW(dumpFile.getWideString().c_str(),
|
||||
GENERIC_WRITE, 0, 0, CREATE_ALWAYS, 0, 0);
|
||||
if (hDumpFile == INVALID_HANDLE_VALUE) return false;
|
||||
|
||||
MINIDUMP_EXCEPTION_INFORMATION mdei;
|
||||
mdei.ThreadId = GetCurrentThreadId();
|
||||
mdei.ExceptionPointers = exceptionInfo;
|
||||
mdei.ClientPointers = TRUE;
|
||||
|
||||
if (MiniDumpWriteDump(GetCurrentProcess(), GetCurrentProcessId(), hDumpFile,
|
||||
MiniDumpNormal, &mdei, 0, NULL)) {
|
||||
CloseHandle(hDumpFile);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
#define HAS_MODULES
|
||||
static void printModules(std::string &out) {
|
||||
HANDLE hProcess = GetCurrentProcess();
|
||||
|
||||
HMODULE modules[1024];
|
||||
DWORD size;
|
||||
if (EnumProcessModules(hProcess, modules, sizeof(modules), &size)) {
|
||||
for (unsigned int i = 0; i < size / sizeof(HMODULE); i++) {
|
||||
char moduleName[512];
|
||||
GetModuleFileNameA(modules[i], moduleName, 512);
|
||||
out.append(moduleName);
|
||||
out.append("\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#define HAS_BACKTRACE
|
||||
static void printBacktrace(std::string &out) {
|
||||
int frameStack = 0;
|
||||
int frameSkip = 3;
|
||||
|
||||
HANDLE hProcess = GetCurrentProcess();
|
||||
|
||||
SymSetOptions(SYMOPT_DEFERRED_LOADS | SYMOPT_INCLUDE_32BIT_MODULES |
|
||||
SYMOPT_FAIL_CRITICAL_ERRORS | SYMOPT_LOAD_LINES |
|
||||
SYMOPT_UNDNAME);
|
||||
|
||||
SymInitialize(hProcess, NULL, TRUE);
|
||||
|
||||
CONTEXT context;
|
||||
RtlCaptureContext(&context);
|
||||
|
||||
char sourceSymMem[sizeof(IMAGEHLP_SYMBOL64) + 1025];
|
||||
PIMAGEHLP_SYMBOL64 sourceSym = (PIMAGEHLP_SYMBOL64)&sourceSymMem;
|
||||
memset(sourceSymMem, 0, sizeof(sourceSymMem));
|
||||
|
||||
IMAGEHLP_LINE64 sourceInfo;
|
||||
memset(&sourceInfo, 0, sizeof(IMAGEHLP_LINE64));
|
||||
sourceInfo.SizeOfStruct = sizeof(IMAGEHLP_LINE64);
|
||||
|
||||
IMAGEHLP_MODULE64 moduleInfo;
|
||||
memset(&moduleInfo, 0, sizeof(moduleInfo));
|
||||
moduleInfo.SizeOfStruct = sizeof(IMAGEHLP_MODULE64);
|
||||
|
||||
STACKFRAME64 stackframe;
|
||||
memset(&stackframe, 0, sizeof(STACKFRAME64));
|
||||
|
||||
#ifdef _WIN64
|
||||
int machineType = IMAGE_FILE_MACHINE_AMD64;
|
||||
stackframe.AddrPC.Offset = context.Rip;
|
||||
stackframe.AddrPC.Mode = AddrModeFlat;
|
||||
stackframe.AddrStack.Offset = context.Rsp;
|
||||
stackframe.AddrStack.Mode = AddrModeFlat;
|
||||
stackframe.AddrFrame.Offset = context.Rbp;
|
||||
stackframe.AddrFrame.Mode = AddrModeFlat;
|
||||
#else
|
||||
int machineType = IMAGE_FILE_MACHINE_I386;
|
||||
stackframe.AddrPC.Offset = context.Eip;
|
||||
stackframe.AddrPC.Mode = AddrModeFlat;
|
||||
stackframe.AddrStack.Offset = context.Esp;
|
||||
stackframe.AddrStack.Mode = AddrModeFlat;
|
||||
stackframe.AddrFrame.Offset = context.Ebp;
|
||||
stackframe.AddrFrame.Mode = AddrModeFlat;
|
||||
#endif
|
||||
|
||||
HANDLE hThread = GetCurrentThread();
|
||||
while (StackWalk64(machineType, hProcess, hThread, &stackframe, &context,
|
||||
NULL, SymFunctionTableAccess64, SymGetModuleBase64,
|
||||
NULL)) {
|
||||
// Skip first frames since they point to this function
|
||||
if (frameStack++ < frameSkip) continue;
|
||||
char numStr[32];
|
||||
memset(numStr, 0, sizeof(numStr));
|
||||
sprintf(numStr, "%3i> ", frameStack - frameSkip);
|
||||
out.append(numStr);
|
||||
|
||||
sourceSym->SizeOfStruct = sizeof(IMAGEHLP_SYMBOL64);
|
||||
sourceSym->MaxNameLength = 1024;
|
||||
|
||||
// Get symbol name
|
||||
DWORD64 displacement64;
|
||||
if (SymGetSymFromAddr64(hProcess, (ULONG64)stackframe.AddrPC.Offset,
|
||||
&displacement64, sourceSym)) {
|
||||
out.append(sourceSym->Name);
|
||||
|
||||
// Get module filename
|
||||
char moduleFile[512];
|
||||
MEMORY_BASIC_INFORMATION mbi;
|
||||
VirtualQuery((LPCVOID)stackframe.AddrPC.Offset, &mbi, sizeof(mbi));
|
||||
GetModuleFileNameA((HMODULE)mbi.AllocationBase, moduleFile, 512);
|
||||
|
||||
// Get source filename and line
|
||||
DWORD displacement32;
|
||||
if (SymGetLineFromAddr64(hProcess, stackframe.AddrPC.Offset,
|
||||
&displacement32, &sourceInfo) != FALSE) {
|
||||
out.append(" {");
|
||||
out.append(filenameOnly(sourceInfo.FileName));
|
||||
out.append(":");
|
||||
out.append(std::to_string(sourceInfo.LineNumber));
|
||||
out.append("}");
|
||||
} else {
|
||||
memset(numStr, 0, sizeof(numStr));
|
||||
sprintf(numStr, " [0x%" PRIx64 "]", stackframe.AddrPC.Offset);
|
||||
out.append(numStr);
|
||||
}
|
||||
out.append(" <");
|
||||
out.append(filenameOnly(moduleFile));
|
||||
out.append(">");
|
||||
}
|
||||
|
||||
out.append("\n");
|
||||
}
|
||||
|
||||
SymCleanup(hProcess);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
LONG WINAPI exceptionHandler(PEXCEPTION_POINTERS info) {
|
||||
static volatile bool handling = false;
|
||||
|
||||
const char *reason = "Unknown";
|
||||
switch (info->ExceptionRecord->ExceptionCode) {
|
||||
case EXCEPTION_ACCESS_VIOLATION:
|
||||
reason = "EXCEPTION_ACCESS_VIOLATION";
|
||||
break;
|
||||
case EXCEPTION_ARRAY_BOUNDS_EXCEEDED:
|
||||
reason = "EXCEPTION_ARRAY_BOUNDS_EXCEEDED";
|
||||
break;
|
||||
case EXCEPTION_DATATYPE_MISALIGNMENT:
|
||||
reason = "EXCEPTION_DATATYPE_MISALIGNMENT";
|
||||
break;
|
||||
case EXCEPTION_FLT_DENORMAL_OPERAND:
|
||||
reason = "EXCEPTION_FLT_DENORMAL_OPERAND";
|
||||
break;
|
||||
case EXCEPTION_FLT_DIVIDE_BY_ZERO:
|
||||
reason = "EXCEPTION_FLT_DIVIDE_BY_ZERO";
|
||||
break;
|
||||
case EXCEPTION_FLT_INEXACT_RESULT:
|
||||
reason = "EXCEPTION_FLT_INEXACT_RESULT";
|
||||
break;
|
||||
case EXCEPTION_FLT_INVALID_OPERATION:
|
||||
reason = "EXCEPTION_FLT_INVALID_OPERATION";
|
||||
break;
|
||||
case EXCEPTION_FLT_OVERFLOW:
|
||||
reason = "EXCEPTION_FLT_OVERFLOW";
|
||||
break;
|
||||
case EXCEPTION_FLT_STACK_CHECK:
|
||||
reason = "EXCEPTION_FLT_STACK_CHECK";
|
||||
break;
|
||||
case EXCEPTION_FLT_UNDERFLOW:
|
||||
reason = "EXCEPTION_FLT_UNDERFLOW";
|
||||
break;
|
||||
case EXCEPTION_ILLEGAL_INSTRUCTION:
|
||||
reason = "EXCEPTION_ILLEGAL_INSTRUCTION";
|
||||
break;
|
||||
case EXCEPTION_IN_PAGE_ERROR:
|
||||
reason = "EXCEPTION_IN_PAGE_ERROR";
|
||||
break;
|
||||
case EXCEPTION_INT_DIVIDE_BY_ZERO:
|
||||
reason = "EXCEPTION_INT_DIVIDE_BY_ZERO";
|
||||
break;
|
||||
case EXCEPTION_INVALID_DISPOSITION:
|
||||
reason = "EXCEPTION_INVALID_DISPOSITION";
|
||||
break;
|
||||
case EXCEPTION_NONCONTINUABLE_EXCEPTION:
|
||||
reason = "EXCEPTION_NONCONTINUABLE_EXCEPTION";
|
||||
break;
|
||||
case EXCEPTION_PRIV_INSTRUCTION:
|
||||
reason = "EXCEPTION_PRIV_INSTRUCTION";
|
||||
break;
|
||||
case EXCEPTION_STACK_OVERFLOW:
|
||||
reason = "EXCEPTION_STACK_OVERFLOW";
|
||||
break;
|
||||
default:
|
||||
return EXCEPTION_CONTINUE_SEARCH;
|
||||
}
|
||||
|
||||
// Avoid new exceptions inside the crash handler
|
||||
if (handling) return EXCEPTION_CONTINUE_SEARCH;
|
||||
|
||||
handling = true;
|
||||
s_exceptionPtr = info;
|
||||
if (CrashHandler::trigger(reason, true)) _Exit(1);
|
||||
handling = false;
|
||||
|
||||
return EXCEPTION_CONTINUE_SEARCH;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
// Linux and Mac OS X platform functions
|
||||
|
||||
#ifndef _WIN32
|
||||
|
||||
static bool sh(std::string &out, const char *cmd) {
|
||||
char buffer[128];
|
||||
FILE *p = popen(cmd, "r");
|
||||
if (p == NULL) return false;
|
||||
while (fgets(buffer, 128, p)) out.append(buffer);
|
||||
pclose(p);
|
||||
return true;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
static bool addr2line(std::string &out, const char *exepath, const char *addr) {
|
||||
char cmd[512];
|
||||
#ifdef OSX
|
||||
sprintf(cmd, "atos -o \"%.400s\" %s 2>&1", exepath, addr);
|
||||
#else
|
||||
sprintf(cmd, "addr2line -f -p -e \"%.400s\" %s 2>&1", exepath, addr);
|
||||
#endif
|
||||
return sh(out, cmd);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
static bool generateMinidump(TFilePath dumpFile) { return false; }
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
static void printModules(std::string &out) {}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#define HAS_BACKTRACE
|
||||
static void printBacktrace(std::string &out) {
|
||||
int frameStack = 0;
|
||||
int frameSkip = 3;
|
||||
|
||||
const int size = 256;
|
||||
void *buffer[size];
|
||||
|
||||
// Get executable path
|
||||
char exepath[512];
|
||||
memset(exepath, 0, 512);
|
||||
if (readlink("/proc/self/exe", exepath, 512) < 0)
|
||||
fprintf(stderr, "Couldn't get exe path\n");
|
||||
|
||||
// Back trace
|
||||
int nptrs = backtrace(buffer, size);
|
||||
char **bts = backtrace_symbols(buffer, nptrs);
|
||||
std::regex re("\\[(.+)\\]");
|
||||
if (bts) {
|
||||
for (int i = 0; i < nptrs; ++i) {
|
||||
// Skip first frames since they point to this function
|
||||
if (frameStack++ < frameSkip) continue;
|
||||
char numStr[32];
|
||||
memset(numStr, 0, sizeof(numStr));
|
||||
sprintf(numStr, "%3i> ", frameStack - frameSkip);
|
||||
out.append(numStr);
|
||||
|
||||
std::string sym = bts[i];
|
||||
std::string line;
|
||||
std::smatch ms;
|
||||
|
||||
bool found = false;
|
||||
if (std::regex_search(sym, ms, re)) {
|
||||
std::string addr = ms[1];
|
||||
if (addr2line(line, exepath, addr.c_str())) {
|
||||
found = (line.rfind("??", 0) != 0);
|
||||
}
|
||||
}
|
||||
|
||||
out.append(found ? line : (sym + "\n"));
|
||||
}
|
||||
}
|
||||
|
||||
free(bts);
|
||||
}
|
||||
|
||||
void signalHandler(int sig) {
|
||||
static volatile bool handling = false;
|
||||
|
||||
const char *reason = "Unknown";
|
||||
switch (sig) {
|
||||
case SIGABRT:
|
||||
reason = "(SIGABRT) Usually caused by an abort() or assert()";
|
||||
break;
|
||||
case SIGFPE:
|
||||
reason = "(SIGFPE) Arithmetic exception, such as divide by zero";
|
||||
break;
|
||||
case SIGILL:
|
||||
reason = "(SIGILL) Illegal instruction";
|
||||
break;
|
||||
case SIGINT:
|
||||
reason = "(SIGINT) Interactive attention signal, (usually ctrl+c)";
|
||||
break;
|
||||
case SIGSEGV:
|
||||
reason = "(SIGSEGV) Segmentation Fault";
|
||||
break;
|
||||
case SIGTERM:
|
||||
reason = "(SIGTERM) A termination request was sent to the program";
|
||||
break;
|
||||
}
|
||||
|
||||
// Avoid new signals inside the crash handler
|
||||
if (handling) return;
|
||||
|
||||
handling = true;
|
||||
if (CrashHandler::trigger(reason, true)) _Exit(1);
|
||||
handling = false;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
static void printSysInfo(std::string &out) {
|
||||
out.append("Build ABI: " + QSysInfo::buildAbi().toStdString() + "\n");
|
||||
out.append("Operating System: " + QSysInfo::prettyProductName().toStdString() + "\n");
|
||||
out.append("OS Kernel: " + QSysInfo::kernelVersion().toStdString() + "\n");
|
||||
out.append("CPU Threads: " + std::to_string(QThread::idealThreadCount()) + "\n");
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
static void printGPUInfo(std::string &out) {
|
||||
const char *gpuVendorName = (const char *)glGetString(GL_VENDOR);
|
||||
const char *gpuModelName = (const char *)glGetString(GL_RENDERER);
|
||||
const char *gpuVersion = (const char *)glGetString(GL_VERSION);
|
||||
if (gpuVendorName)
|
||||
out.append("GPU Vendor: " + std::string(gpuVendorName) + "\n");
|
||||
if (gpuModelName)
|
||||
out.append("GPU Model: " + std::string(gpuModelName) + "\n");
|
||||
if (gpuVersion)
|
||||
out.append("GPU Version: " + std::string(gpuVersion) + "\n");
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
CrashHandler::CrashHandler(QWidget *parent, TFilePath crashFile, QString crashReport)
|
||||
: QDialog(parent), m_crashFile(crashFile), m_crashReport(crashReport) {
|
||||
setWindowFlag(Qt::WindowContextHelpButtonHint, false);
|
||||
|
||||
QStringList sl;
|
||||
sl.append(tr("<b>Tahoma2D crashed unexpectedly.</b>"));
|
||||
sl.append("");
|
||||
sl.append(tr("A crash report has been generated."));
|
||||
sl.append(
|
||||
tr("To report, click 'Open Issue Webpage' to access Tahoma2D's Issues "
|
||||
"page on GitHub."));
|
||||
sl.append(tr("Click on the 'New issue' button and fill out the form."));
|
||||
sl.append("");
|
||||
sl.append(tr("System Configuration and Problem Details:"));
|
||||
|
||||
QLabel *headtext = new QLabel(sl.join("<br>"));
|
||||
headtext->setTextFormat(Qt::RichText);
|
||||
|
||||
QTextEdit *reportTxt = new QTextEdit();
|
||||
reportTxt->setText(crashReport);
|
||||
reportTxt->setReadOnly(true);
|
||||
reportTxt->setLineWrapMode(QTextEdit::LineWrapMode::NoWrap);
|
||||
reportTxt->setStyleSheet(
|
||||
"background:white;\ncolor:black;\nborder:1 solid black;");
|
||||
|
||||
QVBoxLayout *mainLayout = new QVBoxLayout();
|
||||
QHBoxLayout *buttonsLay = new QHBoxLayout();
|
||||
|
||||
QPushButton *copyBtn = new QPushButton(tr("Copy to Clipboard"));
|
||||
QPushButton *webBtn = new QPushButton(tr("Open Issue Webpage"));
|
||||
QPushButton *folderBtn = new QPushButton(tr("Open Reports Folder"));
|
||||
QPushButton *closeBtn = new QPushButton(tr("Close Application"));
|
||||
buttonsLay->addWidget(copyBtn);
|
||||
buttonsLay->addWidget(webBtn);
|
||||
buttonsLay->addWidget(folderBtn);
|
||||
buttonsLay->addWidget(closeBtn);
|
||||
|
||||
mainLayout->addWidget(headtext);
|
||||
mainLayout->addWidget(reportTxt);
|
||||
mainLayout->addLayout(buttonsLay);
|
||||
|
||||
bool ret = connect(copyBtn, SIGNAL(clicked()), this, SLOT(copyClipboard()));
|
||||
ret = ret && connect(webBtn, SIGNAL(clicked()), this, SLOT(openWebpage()));
|
||||
ret = ret && connect(folderBtn, SIGNAL(clicked()), this, SLOT(openFolder()));
|
||||
ret = ret && connect(closeBtn, SIGNAL(clicked()), this, SLOT(accept()));
|
||||
if (!ret) throw TException();
|
||||
|
||||
setWindowTitle(tr("Tahoma2D crashed!"));
|
||||
setLayout(mainLayout);
|
||||
}
|
||||
|
||||
void CrashHandler::reject() {
|
||||
QStringList sl;
|
||||
sl.append(tr("Application is in unstable state and must be restarted."));
|
||||
sl.append(tr("Resuming is not recommended and may lead to an unrecoverable crash."));
|
||||
sl.append(tr("Ignore advice and try to resume program?"));
|
||||
|
||||
QMessageBox::StandardButton reply =
|
||||
QMessageBox::question(this, tr("Ignore crash?"), sl.join("\n"),
|
||||
QMessageBox::Yes | QMessageBox::No);
|
||||
if (reply == QMessageBox::Yes) {
|
||||
QDialog::reject();
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void CrashHandler::copyClipboard() {
|
||||
QClipboard *clipboard = QApplication::clipboard();
|
||||
clipboard->setText(m_crashReport);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void CrashHandler::openWebpage() {
|
||||
QDesktopServices::openUrl(QUrl("https://github.com/tahoma2d/tahoma2d/issues"));
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void CrashHandler::openFolder() {
|
||||
TFilePath fp = ToonzFolder::getCrashReportFolder();
|
||||
QDesktopServices::openUrl(QUrl("file:///" + fp.getQString()));
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void CrashHandler::install() {
|
||||
#ifdef _WIN32
|
||||
// std library seems to override this
|
||||
//SetUnhandledExceptionFilter(exceptionHandler);
|
||||
|
||||
void *handler = AddVectoredExceptionHandler(0, exceptionHandler);
|
||||
assert(handler != NULL);
|
||||
//RemoveVectoredExceptionHandler(handler);
|
||||
#else
|
||||
signal(SIGABRT, signalHandler);
|
||||
signal(SIGFPE, signalHandler);
|
||||
signal(SIGILL, signalHandler);
|
||||
signal(SIGINT, signalHandler);
|
||||
signal(SIGSEGV, signalHandler);
|
||||
signal(SIGTERM, signalHandler);
|
||||
#endif
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void CrashHandler::reportProjectInfo(bool enableReport) {
|
||||
s_reportProjInfo = enableReport;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void CrashHandler::attachParentWindow(QWidget *parent) {
|
||||
s_parentWindow = parent;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
bool CrashHandler::trigger(const QString reason, bool showDialog) {
|
||||
char fileName[128];
|
||||
char dumpName[128];
|
||||
char dateName[128];
|
||||
std::string out;
|
||||
|
||||
// Get time and build filename
|
||||
time_t acc_time;
|
||||
time(&acc_time);
|
||||
struct tm *tm = localtime(&acc_time);
|
||||
strftime(dateName, 128, "%Y-%m-%d %H:%M:%S", tm);
|
||||
strftime(fileName, 128, "Crash-%Y%m%d-%H%M%S.log", tm);
|
||||
strftime(dumpName, 128, "Crash-%Y%m%d-%H%M%S.dmp", tm);
|
||||
TFilePath fpCrsh = ToonzFolder::getCrashReportFolder() + fileName;
|
||||
TFilePath fpDump = ToonzFolder::getCrashReportFolder() + dumpName;
|
||||
|
||||
// Generate minidump
|
||||
#ifdef _WIN32
|
||||
bool minidump = generateMinidump(fpDump, s_exceptionPtr);
|
||||
#else
|
||||
bool minidump = generateMinidump(fpDump);
|
||||
#endif;
|
||||
|
||||
// Generate report
|
||||
try {
|
||||
out.append(TEnv::getApplicationFullName() + " (Build " + __DATE__ ")\n");
|
||||
out.append("\nReport Date: ");
|
||||
out.append(dateName);
|
||||
out.append("\nCrash Reason: ");
|
||||
out.append(reason.toStdString());
|
||||
out.append("\n\n");
|
||||
printSysInfo(out);
|
||||
out.append("\n");
|
||||
printGPUInfo(out);
|
||||
out.append("\nCrash File: ");
|
||||
out.append(fpCrsh.getQString().toStdString());
|
||||
#ifdef HAS_MINIDUMP
|
||||
out.append("\nMini Dump File: ");
|
||||
if (minidump)
|
||||
out.append(fpDump.getQString().toStdString());
|
||||
else
|
||||
out.append("Failed");
|
||||
#endif
|
||||
out.append("\n");
|
||||
} catch (...) {
|
||||
}
|
||||
try {
|
||||
if (s_reportProjInfo) {
|
||||
TProjectManager *pm = TProjectManager::instance();
|
||||
TApp *app = TApp::instance();
|
||||
|
||||
TProjectP currentProject = pm->getCurrentProject();
|
||||
TFilePath projectPath = currentProject->getProjectPath();
|
||||
|
||||
ToonzScene *currentScene = app->getCurrentScene()->getScene();
|
||||
std::wstring sceneName = currentScene->getSceneName();
|
||||
|
||||
out.append("\nApplication Dir: ");
|
||||
out.append(QCoreApplication::applicationDirPath().toStdString());
|
||||
out.append("\nStuff Dir: ");
|
||||
out.append(TEnv::getStuffDir().getQString().toStdString());
|
||||
out.append("\n");
|
||||
out.append("\nProject Name: ");
|
||||
out.append(currentProject->getName().getQString().toStdString());
|
||||
out.append("\nScene Name: ");
|
||||
out.append(QString::fromStdWString(sceneName).toStdString());
|
||||
out.append("\nProject Path: ");
|
||||
out.append(projectPath.getQString().toStdString());
|
||||
out.append("\nScene Path: ");
|
||||
out.append(currentScene->getScenePath().getQString().toStdString());
|
||||
out.append("\n");
|
||||
}
|
||||
} catch (...) {
|
||||
}
|
||||
#ifdef HAS_BACKTRACE
|
||||
try {
|
||||
out.append("\n==== Backtrace ====\n");
|
||||
printBacktrace(out);
|
||||
out.append("==== End ====\n");
|
||||
} catch (...) {
|
||||
}
|
||||
#endif
|
||||
#ifdef HAS_MODULES
|
||||
try {
|
||||
out.append("\n==== Modules ====\n");
|
||||
printModules(out);
|
||||
out.append("==== End ====\n");
|
||||
} catch (...) {
|
||||
}
|
||||
#endif
|
||||
|
||||
// Save to crash information to file
|
||||
FILE *fw = fopen(fpCrsh, "w");
|
||||
if (fw != NULL) {
|
||||
fwrite(out.c_str(), 1, out.size(), fw);
|
||||
fclose(fw);
|
||||
}
|
||||
|
||||
if (showDialog) {
|
||||
// Show crash handler dialog
|
||||
CrashHandler crashdialog(s_parentWindow, fpCrsh, QString::fromStdString(out));
|
||||
return crashdialog.exec() != QDialog::Rejected;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
33
toonz/sources/toonz/crashhandler.h
Normal file
33
toonz/sources/toonz/crashhandler.h
Normal file
|
@ -0,0 +1,33 @@
|
|||
#pragma once
|
||||
|
||||
#ifndef CRASHHANDLER_INCLUDED
|
||||
#define CRASHHANDLER_INCLUDED
|
||||
|
||||
#include "tcommon.h"
|
||||
#include "tfilepath.h"
|
||||
|
||||
#include <QDialog>
|
||||
|
||||
class CrashHandler : public QDialog {
|
||||
Q_OBJECT;
|
||||
|
||||
TFilePath m_crashFile;
|
||||
QString m_crashReport;
|
||||
|
||||
public:
|
||||
CrashHandler(QWidget *parent, TFilePath crashFile, QString crashTxt);
|
||||
|
||||
void reject();
|
||||
|
||||
static void install();
|
||||
static void reportProjectInfo(bool enableReport);
|
||||
static void attachParentWindow(QWidget *parent);
|
||||
static bool trigger(const QString reason, bool showDialog);
|
||||
|
||||
public slots:
|
||||
void copyClipboard();
|
||||
void openWebpage();
|
||||
void openFolder();
|
||||
};
|
||||
|
||||
#endif // CRASHHANDLER_INCLUDED
|
|
@ -1,9 +1,7 @@
|
|||
// Soli Deo gloria
|
||||
#ifdef WITH_CRASHRPT
|
||||
#include <tchar.h>
|
||||
#endif
|
||||
|
||||
// Tnz6 includes
|
||||
#include "crashhandler.h"
|
||||
#include "mainwindow.h"
|
||||
#include "flipbook.h"
|
||||
#include "tapp.h"
|
||||
|
@ -70,10 +68,6 @@
|
|||
|
||||
#include "kis_tablet_support_win8.h"
|
||||
|
||||
#ifdef WITH_CRASHRPT
|
||||
#include "CrashRpt.h"
|
||||
#endif
|
||||
|
||||
#ifdef MACOSX
|
||||
#include "tipc.h"
|
||||
#endif
|
||||
|
@ -258,18 +252,23 @@ static void script_output(int type, const QString &value) {
|
|||
|
||||
int main(int argc, char *argv[]) {
|
||||
#ifdef Q_OS_WIN
|
||||
// Enable standard input/output on Windows Platform for debug
|
||||
BOOL consoleAttached = ::AttachConsole(ATTACH_PARENT_PROCESS);
|
||||
if (consoleAttached) {
|
||||
// Enable standard input/output on Windows Platform for debug
|
||||
if (::AttachConsole(ATTACH_PARENT_PROCESS)) {
|
||||
freopen("CON", "r", stdin);
|
||||
freopen("CON", "w", stdout);
|
||||
freopen("CON", "w", stderr);
|
||||
atexit([]() {
|
||||
::FreeConsole();
|
||||
});
|
||||
}
|
||||
#endif
|
||||
|
||||
// Build icon map
|
||||
ThemeManager::getInstance().buildIconPathsMap(":/icons");
|
||||
|
||||
// Install signal handlers to catch crashes
|
||||
CrashHandler::install();
|
||||
|
||||
// parsing arguments and qualifiers
|
||||
TFilePath loadFilePath;
|
||||
QString argumentLayoutFileName = "";
|
||||
|
@ -578,34 +577,6 @@ int main(int argc, char *argv[]) {
|
|||
// Toonz environment
|
||||
initToonzEnv(argumentPathValues);
|
||||
|
||||
#ifdef WITH_CRASHRPT
|
||||
std::string str;
|
||||
|
||||
CR_INSTALL_INFO pInfo;
|
||||
memset(&pInfo, 0, sizeof(CR_INSTALL_INFO));
|
||||
pInfo.cb = sizeof(CR_INSTALL_INFO);
|
||||
|
||||
str = TEnv::getApplicationName();
|
||||
std::wstring wAppName = std::wstring(str.begin(), str.end());
|
||||
pInfo.pszAppName = wAppName.c_str();
|
||||
|
||||
str = TEnv::getApplicationVersion();
|
||||
std::wstring wAppVersion = std::wstring(str.begin(), str.end());
|
||||
pInfo.pszAppVersion = wAppVersion.c_str();
|
||||
|
||||
TFilePath crashrptCache =
|
||||
ToonzFolder::getCacheRootFolder() + TFilePath("crashrpt");
|
||||
str = crashrptCache.getQString().toStdString();
|
||||
std::wstring wRptdir = std::wstring(str.begin(), str.end());
|
||||
pInfo.pszErrorReportSaveDir = wRptdir.c_str();
|
||||
|
||||
// Install all available exception handlers.
|
||||
// Don't send reports automaticall, store locally
|
||||
pInfo.dwFlags |= CR_INST_ALL_POSSIBLE_HANDLERS | CR_INST_DONT_SEND_REPORT;
|
||||
|
||||
crInstall(&pInfo);
|
||||
#endif
|
||||
|
||||
// prepare for 30bit display
|
||||
if (Preferences::instance()->is30bitDisplayEnabled()) {
|
||||
QSurfaceFormat sFmt = QSurfaceFormat::defaultFormat();
|
||||
|
@ -703,6 +674,8 @@ int main(int argc, char *argv[]) {
|
|||
|
||||
/*-- Layoutファイル名をMainWindowのctorに渡す --*/
|
||||
MainWindow w(argumentLayoutFileName);
|
||||
CrashHandler::attachParentWindow(&w);
|
||||
CrashHandler::reportProjectInfo(true);
|
||||
|
||||
TFilePath fp = ToonzFolder::getModuleFile("mainwindow.ini");
|
||||
QSettings settings(toQString(fp), QSettings::IniFormat);
|
||||
|
@ -911,15 +884,5 @@ int main(int argc, char *argv[]) {
|
|||
TUndoManager::manager()->reset();
|
||||
PreviewFxManager::instance()->reset();
|
||||
|
||||
#ifdef _WIN32
|
||||
if (consoleAttached) {
|
||||
::FreeConsole();
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef WITH_CRASHRPT
|
||||
crUninstall();
|
||||
#endif
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -125,6 +125,20 @@ TFilePath ToonzFolder::getCacheRootFolder() {
|
|||
return (state == OK) ? TFilePath(cacheDir) : TFilePath();
|
||||
}
|
||||
|
||||
TFilePath ToonzFolder::getCrashReportFolder() {
|
||||
static enum STATE { FIRSTTIME, OK, NG } state = FIRSTTIME;
|
||||
QString crashDir =
|
||||
QStandardPaths::writableLocation(QStandardPaths::AppLocalDataLocation) +
|
||||
"/crash";
|
||||
if (state == FIRSTTIME) {
|
||||
if (QDir(crashDir).mkpath("."))
|
||||
state = OK;
|
||||
else
|
||||
state = NG;
|
||||
}
|
||||
return (state == OK) ? TFilePath(crashDir) : TFilePath();
|
||||
}
|
||||
|
||||
TFilePath ToonzFolder::getProfileFolder() {
|
||||
TFilePath fp = getSystemVarPathValue(getSystemVarPrefix() + "PROFILES");
|
||||
if (fp == TFilePath())
|
||||
|
|
Loading…
Reference in a new issue