TTKMusicPlayer  3.7.0.0
TTKMusicPlayer imitates Kugou UI, the music player uses of qmmp core library based on Qt for windows and linux
ttkdumper.cpp
Go to the documentation of this file.
1 #include "ttkdumper.h"
2 #include "ttkversion.h"
3 #include "miniprocess.h"
4 
5 #ifdef Q_OS_WIN
6 # define WIN32_LEAN_AND_MEAN
7 # include <qt_windows.h>
8 # include <dbghelp.h>
9 #elif defined Q_OS_UNIX
10 # include <signal.h>
11 # include <execinfo.h>
12 # include <unistd.h>
13 # include <fcntl.h>
14 #endif
15 
19 class TTKDumperPrivate : public TTKPrivate<TTKDumper>
20 {
21 public:
23 
24 #ifdef Q_OS_WIN
25  typedef BOOL (WINAPI *MINIDUMPWRITEDUMP)(HANDLE hProcess, DWORD dwPid, HANDLE hFile, MINIDUMP_TYPE DumpType,
26  CONST PMINIDUMP_EXCEPTION_INFORMATION ExceptionParam,
27  CONST PMINIDUMP_USER_STREAM_INFORMATION UserStreamParam,
28  CONST PMINIDUMP_CALLBACK_INFORMATION CallbackParam);
29 
30  static constexpr int MAX_WARNING_MESSAGE_PATH = 1024;
31  static constexpr int MAX_DUMP_FILE_NUMBER = 9999;
32 
33  static LONG WINAPI errorHandler(EXCEPTION_POINTERS *info);
34 #elif defined Q_OS_UNIX
35  static void errorHandler(int id);
36 #endif
37 
38  void initialize();
39 
40  static QString m_name;
41  static QString m_version;
43 };
44 
48 
50 {
51 
52 }
53 
54 #ifdef Q_OS_WIN
56 {
57  ::SetUnhandledExceptionFilter(errorHandler);
58 }
59 
60 LONG TTKDumperPrivate::errorHandler(EXCEPTION_POINTERS *info)
61 {
62  if(m_functor)
63  {
64  m_functor();
65  }
66 
67  LONG retval = EXCEPTION_CONTINUE_SEARCH;
68 
69  // firstly see if dbghelp.dll is around and has the function we need
70  // look next to the EXE first, as the one in System32 might be old
71  // (e.g. Windows 2000)
72  HMODULE instance = nullptr;
73  WCHAR dbgHelpPath[_MAX_PATH];
74 
75  if(GetModuleFileNameW(nullptr, dbgHelpPath, _MAX_PATH))
76  {
77  WCHAR *slash = wcsrchr(dbgHelpPath, L'\\');
78  if(slash)
79  {
80  wcscpy(slash + 1, L"DBGHELP.DLL");
81  instance = LoadLibraryW(dbgHelpPath);
82  }
83  }
84 
85  if(instance == nullptr)
86  {
87  // load any version we can
88  instance = LoadLibraryW(L"DBGHELP.DLL");
89  }
90 
91  if(instance)
92  {
93  MINIDUMPWRITEDUMP dump = TTKVoidCast(MINIDUMPWRITEDUMP)GetProcAddress(instance, "MiniDumpWriteDump");
94  if(dump)
95  {
96  WCHAR dumpPath[_MAX_PATH];
97  WCHAR dumpRootPath[_MAX_PATH];
98  WCHAR scratch[_MAX_PATH];
99 
100  // work out a good place for the dump file
101  if(GetModuleFileNameW(nullptr, dbgHelpPath, _MAX_PATH))
102  {
103  WCHAR *slash = wcsrchr(dbgHelpPath, L'\\');
104  if(slash)
105  {
106  wcscpy(slash + 1, L"");
107  wcscpy(dumpPath, dbgHelpPath);
108  }
109  }
110  else if(!GetTempPathW(_MAX_PATH, dumpPath))
111  {
112  wcscpy(dumpPath, L"c:\\temp\\");
113  }
114  wcscpy(dumpRootPath, dumpPath);
115 
116  // ask the user if they want to save a dump file
117  //if(::MessageBox(nullptr, _T("Something bad happened in your program, would you like to save a diagnostic file?"), m_szAppName, MB_YESNO)==IDYES)
118  {
119  HANDLE file = INVALID_HANDLE_VALUE;
120  int i = 1;
121  WCHAR fileNumber[_MAX_PATH];
122  while(file == INVALID_HANDLE_VALUE)
123  {
124  swprintf(fileNumber, sizeof(fileNumber), L"_%04d",i);
125  wcscpy(dumpPath, dumpRootPath);
126  wcscat(dumpPath, m_name.toStdWString().c_str());
127  wcscat(dumpPath, L"_");
128  wcscat(dumpPath, m_version.toStdWString().c_str());
129  wcscat(dumpPath, fileNumber);
130  wcscat(dumpPath, L".dmp");
131 
132  file = ::CreateFileW(dumpPath, GENERIC_WRITE, FILE_SHARE_WRITE, nullptr, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, nullptr);
133  i++;
134  if(i > MAX_DUMP_FILE_NUMBER)
135  {
136  file = ::CreateFileW(dumpPath, GENERIC_WRITE, FILE_SHARE_WRITE, nullptr, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr);
137  break;
138  }
139  }
140  // create the file
141  if(file != INVALID_HANDLE_VALUE)
142  {
143  MINIDUMP_EXCEPTION_INFORMATION exInfo;
144  exInfo.ThreadId = ::GetCurrentThreadId();
145  exInfo.ExceptionPointers = info;
146  exInfo.ClientPointers = 0;
147 
148  // write the dump
149  BOOL ok = dump(GetCurrentProcess(), GetCurrentProcessId(), file, MiniDumpNormal, &exInfo, nullptr, nullptr);
150  if(ok)
151  {
152  swprintf(scratch, sizeof(scratch), L"Saved dump file to '%s'", dumpPath);
153  retval = EXCEPTION_EXECUTE_HANDLER;
154  }
155  else
156  {
157  swprintf(scratch, sizeof(scratch), L"Failed to save dump file to '%s' (error %d)", dumpPath, GetLastError());
158  }
159  ::CloseHandle(file);
160 
161  WCHAR outMessage[MAX_WARNING_MESSAGE_PATH];
162  swprintf(outMessage, sizeof(outMessage), outMessage, m_name.toStdWString().c_str(), dumpPath);
163  }
164  else
165  {
166  swprintf(scratch, sizeof(scratch), L"Failed to create dump file '%s' (error %d)", dumpPath, GetLastError());
167  }
168  }
169  }
170  }
171  return retval;
172 }
173 #elif defined Q_OS_UNIX
174 void TTKDumperPrivate::errorHandler(int id)
175 {
176  TTK_INFO_STREAM("Application error occurred, error code " << id);
177  if(m_functor)
178  {
179  m_functor();
180  }
181 
182  char stamp[50];
183  sprintf(stamp, "%ld", time(nullptr));
184  const TTKString &file_name = (m_name + '_' + m_version).toStdString() + "." + stamp + ".dmp";
185 
186  constexpr int size = 512;
187  void* array[size];
188  const int fd = open(file_name.c_str(), O_CREAT | O_WRONLY, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);
189  backtrace_symbols_fd(array, backtrace(array, size), fd);
190  close(fd);
191 
192  raise(id);
193  exit(0);
194 }
195 
197 {
198  signal(SIGPIPE, errorHandler);
199  signal(SIGSEGV, errorHandler);
200  signal(SIGFPE, errorHandler);
201  signal(SIGABRT, errorHandler);
202  signal(SIGBUS, errorHandler);
203  signal(SIGILL, errorHandler);
204  signal(SIGINT, errorHandler);
205  signal(SIGTERM, errorHandler);
206 }
207 #endif
208 
209 
210 
212 {
213  TTKDumperPrivate::m_name = "TTK";
215 }
216 
218 {
219  TTKDumperPrivate::m_name = "TTK";
221  TTKDumperPrivate::m_functor = functor;
222 }
223 
225 {
227  {
229  }
230 }
231 
233 {
234  TTK_D(TTKDumper);
235  d->initialize();
236 }
#define TTKVoidCast(x)
Definition: ttkqtglobal.h:66
The class of the ttk dumper.
Definition: ttkdumper.h:39
voidpf void uLong size
Definition: ioapi.h:136
#define INVALID_HANDLE_VALUE
Definition: iowin32.c:21
The class of the ttk dumper private.
Definition: ttkdumper.cpp:19
std::string TTKString
Definition: ttkglobal.h:121
#define TTK_INFO_STREAM(msg)
Definition: ttklogger.h:67
#define TTK_VERSION_STR
Definition: ttkversion.h:171
static QString m_name
Definition: ttkdumper.cpp:40
static QString m_version
Definition: ttkdumper.cpp:41
std::function< void(void)> TTKDumperFunctor
Definition: ttkdumper.h:34
static TTKDumperFunctor m_functor
Definition: ttkdumper.cpp:42
void run()
Definition: ttkdumper.cpp:232
The class of the ttk private base.
Definition: ttkprivate.h:48
#define TTK_D(Class)
Definition: ttkprivate.h:41