17 #include <boost/filesystem.hpp> 18 #include <boost/date_time.hpp> 20 #include <pion/config.hpp> 21 #include <pion/process.hpp> 22 #include <pion/logger.hpp> 28 boost::once_flag process::m_instance_flag = BOOST_ONCE_INIT;
29 process::config_type *process::m_config_ptr = NULL;
52 void process::create_config(
void)
55 m_config_ptr = &UNIQUE_PION_PROCESS_CONFIG;
62 BOOL WINAPI console_ctrl_handler(DWORD ctrl_type)
66 case CTRL_BREAK_EVENT:
67 case CTRL_CLOSE_EVENT:
68 case CTRL_SHUTDOWN_EVENT:
76 void process::set_dumpfile_directory(
const std::string& dir)
79 static const TCHAR* DBGHELP_DLL = _T(
"DBGHELP.DLL");
81 if (!dir.empty() && !boost::filesystem::is_directory(dir)) {
82 throw dumpfile_init_exception(
"Dump file directory doesn't exist: " + dir);
85 cfg.dumpfile_dir = dir;
90 TCHAR szDbgHelpPath[_MAX_PATH];
93 if (GetModuleFileName(NULL, szDbgHelpPath, _MAX_PATH)) {
94 TCHAR *pSlash = _tcsrchr(szDbgHelpPath, _T(
'\\'));
96 _tcscpy(pSlash+1, DBGHELP_DLL);
97 hDll = ::LoadLibrary( szDbgHelpPath );
102 hDll = ::LoadLibrary( DBGHELP_DLL );
104 cfg.h_dbghelp = hDll;
107 throw dumpfile_init_exception(
"Failed to load DbgHelp.dll");
110 cfg.h_dbghelp = NULL;
114 if (cfg.h_dbghelp != NULL) {
115 cfg.p_dump_proc = (MINIDUMPWRITEDUMP)::GetProcAddress(cfg.h_dbghelp,
"MiniDumpWriteDump");
117 if (cfg.p_dump_proc == NULL) {
118 throw dumpfile_init_exception(
"Failed to get MiniDumpWriteDump proc address, probably dbghelp.dll version is too old");
121 cfg.p_dump_proc = NULL;
126 if (cfg.p_dump_proc) {
127 ::SetUnhandledExceptionFilter(process::unhandled_exception_filter);
128 PION_LOG_INFO(_logger,
"Dump file generation enabled to " << cfg.dumpfile_dir );
130 ::SetUnhandledExceptionFilter(NULL);
131 PION_LOG_INFO(_logger,
"Unhandled exception handling reset to default");
135 std::string process::generate_dumpfile_name()
140 using namespace boost::posix_time;
141 static std::locale loc(std::cout.getloc(),
new time_facet(
"%Y%m%d_%H%M%S"));
142 std::stringstream ss;
144 ss << second_clock::universal_time() <<
".dmp";
147 boost::filesystem::path p(boost::filesystem::system_complete(cfg.dumpfile_dir));
152 # if defined(BOOST_FILESYSTEM_VERSION) && BOOST_FILESYSTEM_VERSION >= 3 155 return p.file_string();
160 LONG WINAPI process::unhandled_exception_filter(
struct _EXCEPTION_POINTERS *pExceptionInfo)
166 if (cfg.dumpfile_dir.empty() || cfg.p_dump_proc == NULL) {
167 PION_LOG_FATAL(_logger,
"Unhandled exception caught when dump file handling not configured!");
168 PION_SHUTDOWN_LOGGER;
169 return EXCEPTION_CONTINUE_SEARCH;
172 std::string dumpfile_path = generate_dumpfile_name();
173 LONG rc = EXCEPTION_CONTINUE_SEARCH;
176 HANDLE hFile = ::CreateFile(dumpfile_path.c_str(), GENERIC_WRITE, FILE_SHARE_WRITE, NULL, CREATE_ALWAYS,
177 FILE_ATTRIBUTE_NORMAL, NULL);
179 if (hFile!=INVALID_HANDLE_VALUE) {
180 _MINIDUMP_EXCEPTION_INFORMATION ExInfo;
182 ExInfo.ThreadId = ::GetCurrentThreadId();
183 ExInfo.ExceptionPointers = pExceptionInfo;
184 ExInfo.ClientPointers = NULL;
187 BOOL bOK = cfg.p_dump_proc(GetCurrentProcess(), GetCurrentProcessId(), hFile, MiniDumpNormal, &ExInfo, NULL, NULL );
190 PION_LOG_INFO(_logger,
"Saved process dump file to " << dumpfile_path);
192 PION_LOG_ERROR(_logger,
"Failed to save dump file to " << dumpfile_path <<
193 " error code: " << GetLastError());
196 ::CloseHandle(hFile);
197 rc = EXCEPTION_EXECUTE_HANDLER;
199 PION_LOG_ERROR(_logger,
"Failed to create dump file " << dumpfile_path <<
200 " error code: " << GetLastError());
203 PION_LOG_FATAL(_logger,
"Unhandled exception caught. The process will be terminated!");
204 PION_SHUTDOWN_LOGGER;
211 SetConsoleCtrlHandler(console_ctrl_handler, TRUE);
219 #else // NOT #ifdef _MSC_VER 221 void handle_signal(
int sig)
228 signal(SIGPIPE, SIG_IGN);
229 signal(SIGCHLD, SIG_IGN);
230 signal(SIGTSTP, SIG_IGN);
231 signal(SIGTTOU, SIG_IGN);
232 signal(SIGTTIN, SIG_IGN);
233 signal(SIGHUP, SIG_IGN);
234 signal(SIGINT, handle_signal);
235 signal(SIGTERM, handle_signal);
244 if(getppid()==1)
return;
257 for (i=getdtablesize();i>=0;--i) close(i);
260 i=open(
"/dev/null",O_RDWR);
270 #endif // #ifdef _MSC_VER static void daemonize(void)
fork process and run as a background daemon
bool shutdown_now
true if we should shutdown now
data type for static/global process configuration information
static void wait_for_shutdown(void)
blocks until the shutdown condition has been signaled
boost::mutex shutdown_mutex
used to protect the shutdown condition
static void shutdown(void)
signals the shutdown condition
boost::condition shutdown_cond
triggered when it is time to shutdown
static void initialize(void)
sets up basic signal handling for the process
static config_type & get_config(void)
returns a singleton instance of config_type