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));
153 # if defined(BOOST_FILESYSTEM_VERSION) && BOOST_FILESYSTEM_VERSION >= 3 156 return p.file_string();
161 LONG WINAPI process::unhandled_exception_filter(
struct _EXCEPTION_POINTERS *pExceptionInfo)
167 if (cfg.dumpfile_dir.empty() || cfg.p_dump_proc == NULL) {
168 PION_LOG_FATAL(_logger,
"Unhandled exception caught when dump file handling not configured!");
169 PION_SHUTDOWN_LOGGER;
170 return EXCEPTION_CONTINUE_SEARCH;
173 std::string dumpfile_path = generate_dumpfile_name();
174 LONG rc = EXCEPTION_CONTINUE_SEARCH;
177 HANDLE hFile = ::CreateFile(dumpfile_path.c_str(), GENERIC_WRITE, FILE_SHARE_WRITE, NULL, CREATE_ALWAYS,
178 FILE_ATTRIBUTE_NORMAL, NULL);
180 if (hFile!=INVALID_HANDLE_VALUE) {
181 _MINIDUMP_EXCEPTION_INFORMATION ExInfo;
183 ExInfo.ThreadId = ::GetCurrentThreadId();
184 ExInfo.ExceptionPointers = pExceptionInfo;
185 ExInfo.ClientPointers = NULL;
188 BOOL bOK = cfg.p_dump_proc(GetCurrentProcess(), GetCurrentProcessId(), hFile, MiniDumpNormal, &ExInfo, NULL, NULL );
191 PION_LOG_INFO(_logger,
"Saved process dump file to " << dumpfile_path);
193 PION_LOG_ERROR(_logger,
"Failed to save dump file to " << dumpfile_path <<
194 " error code: " << GetLastError());
197 ::CloseHandle(hFile);
198 rc = EXCEPTION_EXECUTE_HANDLER;
200 PION_LOG_ERROR(_logger,
"Failed to create dump file " << dumpfile_path <<
201 " error code: " << GetLastError());
204 PION_LOG_FATAL(_logger,
"Unhandled exception caught. The process will be terminated!");
205 PION_SHUTDOWN_LOGGER;
212 SetConsoleCtrlHandler(console_ctrl_handler, TRUE);
220 #else // NOT #ifdef _MSC_VER 222 void handle_signal(
int sig)
229 signal(SIGPIPE, SIG_IGN);
230 signal(SIGCHLD, SIG_IGN);
231 signal(SIGTSTP, SIG_IGN);
232 signal(SIGTTOU, SIG_IGN);
233 signal(SIGTTIN, SIG_IGN);
234 signal(SIGHUP, SIG_IGN);
235 signal(SIGINT, handle_signal);
236 signal(SIGTERM, handle_signal);
245 if(getppid()==1)
return;
258 for (i=getdtablesize();i>=0;--i) close(i);
261 i=open(
"/dev/null",O_RDWR);
271 #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