1 #include "../../stdafx.h"
3 #include "win32_exception.h"
5 #include <boost/thread.hpp>
6 #include <boost/lexical_cast.hpp>
8 #include "../../thread_info.h"
11 namespace caspar { namespace detail {
13 typedef struct tagTHREADNAME_INFO
15 DWORD dwType; // must be 0x1000
16 LPCSTR szName; // pointer to name (in user addr space)
17 DWORD dwThreadID; // thread ID (-1=caller thread)
18 DWORD dwFlags; // reserved for future use, must be zero
21 inline void SetThreadName(DWORD dwThreadID, LPCSTR szThreadName)
26 info.szName = szThreadName;
27 info.dwThreadID = dwThreadID;
32 RaiseException( 0x406D1388, 0, sizeof(info)/sizeof(ULONG_PTR), (ULONG_PTR*)&info );
34 __except (EXCEPTION_CONTINUE_EXECUTION){}
39 bool& installed_for_thread()
41 static boost::thread_specific_ptr<bool> installed;
43 auto for_thread = installed.get();
47 for_thread = new bool(false);
48 installed.reset(for_thread);
54 void install_gpf_handler()
57 _set_se_translator(win32_exception::Handler);
58 installed_for_thread() = true;
62 void ensure_gpf_handler_installed_for_thread(
63 const char* thread_description)
65 if (!installed_for_thread())
67 install_gpf_handler();
69 if (thread_description)
71 detail::SetThreadName(GetCurrentThreadId(), thread_description);
72 get_thread_info().name = thread_description;
77 msg_info_t generate_message(const EXCEPTION_RECORD& info)
79 switch (info.ExceptionCode)
81 case EXCEPTION_ACCESS_VIOLATION:
83 bool is_write = info.ExceptionInformation[0] == 1;
84 auto bad_address = reinterpret_cast<const void*>(info.ExceptionInformation[1]);
85 auto location = info.ExceptionAddress;
87 return "Access violation at " + boost::lexical_cast<std::string>(location) + " trying to " + (is_write ? "write " : "read ") + boost::lexical_cast<std::string>(bad_address);
89 case EXCEPTION_FLT_DIVIDE_BY_ZERO:
90 case EXCEPTION_INT_DIVIDE_BY_ZERO:
91 return "Divide by zero";
93 return "Win32 exception";
97 void win32_exception::Handler(unsigned int errorCode, EXCEPTION_POINTERS* pInfo) {
100 case EXCEPTION_ACCESS_VIOLATION:
101 CASPAR_THROW_EXCEPTION(win32_access_violation() << generate_message(*(pInfo->ExceptionRecord)));
102 case EXCEPTION_STACK_OVERFLOW:
103 throw "Stack overflow. Not generating stack trace to protect from further overflowing the stack";
105 CASPAR_THROW_EXCEPTION(win32_exception() << generate_message(*(pInfo->ExceptionRecord)));