improved minidump generation
authorVictor Kirhenshtein <victor@netxms.org>
Mon, 30 Oct 2017 11:18:12 +0000 (13:18 +0200)
committerVictor Kirhenshtein <victor@netxms.org>
Mon, 30 Oct 2017 11:19:10 +0000 (13:19 +0200)
src/libnetxms/seh.cpp
src/server/core/debug.cpp
src/server/netxmsd/netxmsd.cpp

index 0868aeb..d37709e 100644 (file)
@@ -251,7 +251,6 @@ BOOL LIBNETXMS_EXPORTABLE SEHServiceExceptionHandler(EXCEPTION_POINTERS *pInfo)
        TCHAR szWindowsVersion[256] = _T("ERROR"), szInfoFile[MAX_PATH], szDumpFile[MAX_PATH], szProcNameUppercase[64];
        HANDLE hFile;
        time_t t;
-       MINIDUMP_EXCEPTION_INFORMATION mei;
    SYSTEM_INFO sysInfo;
 
        t = time(NULL);
@@ -334,17 +333,30 @@ BOOL LIBNETXMS_EXPORTABLE SEHServiceExceptionHandler(EXCEPTION_POINTERS *pInfo)
        }
 
        // Create minidump
-       _sntprintf(szDumpFile, MAX_PATH, _T("%s\\%s-%d-%u.mdmp"),
+       _sntprintf(szDumpFile, MAX_PATH, _T("%s\\%s-%u-%u.mdmp"),
                   m_szDumpDir, m_szBaseProcessName, GetCurrentProcessId(), (DWORD)t);
    hFile = CreateFile(szDumpFile, GENERIC_WRITE, 0, NULL,
                       CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
    if (hFile != INVALID_HANDLE_VALUE)
    {
+       MINIDUMP_EXCEPTION_INFORMATION mei;
                mei.ThreadId = GetCurrentThreadId();
                mei.ExceptionPointers = pInfo;
                mei.ClientPointers = FALSE;
+
+      static const TCHAR *comments = _T("Version: ") NETXMS_VERSION_STRING _T("\nBuild tag: ") NETXMS_BUILD_TAG;
+      MINIDUMP_USER_STREAM us;
+      us.Type = CommentStreamW;
+      us.Buffer = (void*)comments;
+      us.BufferSize = static_cast<ULONG>(_tcslen(comments) * sizeof(TCHAR));
+
+      MINIDUMP_USER_STREAM_INFORMATION usi;
+      usi.UserStreamCount = 1;
+      usi.UserStreamArray = &us;
+
       MiniDumpWriteDump(GetCurrentProcess(), GetCurrentProcessId(), hFile,
-                                 m_writeFullDump ? MiniDumpWithDataSegs : MiniDumpNormal, &mei, NULL, NULL);
+            static_cast<MINIDUMP_TYPE>((m_writeFullDump ? MiniDumpWithFullMemory : MiniDumpNormal) | MiniDumpWithHandleData | MiniDumpWithProcessThreadData),
+            &mei, &usi, NULL);
       CloseHandle(hFile);
    }
 
index 78a93a9..ee6a4e7 100644 (file)
@@ -277,17 +277,17 @@ LONG GetThreadPoolStat(ThreadPoolStat stat, const TCHAR *param, TCHAR *value)
 
 void DumpProcess(CONSOLE_CTX console)
 {
-       STARTUPINFOA si;
-       PROCESS_INFORMATION pi;
-       char cmdLine[64];
-
        ConsolePrintf(console, _T("Dumping process to disk...\n"));
 
-       sprintf(cmdLine, "netxmsd.exe --dump %d", GetCurrentProcessId());
+       TCHAR cmdLine[MAX_PATH + 64];
+       _sntprintf(cmdLine, MAX_PATH + 64, _T("netxmsd.exe --dump-dir \"%s\" --dump %d"), g_szDumpDir, GetCurrentProcessId());
+
+       PROCESS_INFORMATION pi;
+   STARTUPINFO si;
        memset(&si, 0, sizeof(STARTUPINFO));
        si.cb = sizeof(STARTUPINFO);
-       if (CreateProcessA(NULL, cmdLine, NULL, NULL, FALSE,
-                          (g_flags & AF_DAEMON) ? CREATE_NO_WINDOW : 0, NULL, NULL, &si, &pi))
+       if (CreateProcess(NULL, cmdLine, NULL, NULL, FALSE,
+            (g_flags & AF_DAEMON) ? CREATE_NO_WINDOW : 0, NULL, NULL, &si, &pi))
        {
                WaitForSingleObject(pi.hProcess, INFINITE);
                CloseHandle(pi.hThread);
index a13f144..8992b54 100644 (file)
@@ -127,11 +127,24 @@ static void CreateMiniDump(DWORD pid)
        hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid);
        if (hProcess != NULL)
        {
-               hFile = CreateFile(_T("C:\\netxmsd.mdmp"), GENERIC_WRITE, 0, NULL,
+      TCHAR fname[MAX_PATH];
+      _sntprintf(fname, MAX_PATH, _T("%s\\netxmsd-%u-%u.mdmp"), g_szDumpDir, pid, time(NULL));
+               hFile = CreateFile(fname, GENERIC_WRITE, 0, NULL,
                                                                 CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
                if (hFile != INVALID_HANDLE_VALUE)
                {
-                       MiniDumpWriteDump(hProcess, pid, hFile, MiniDumpWithDataSegs, NULL, NULL, NULL);
+         static const TCHAR *comments = _T("Version: ") NETXMS_VERSION_STRING _T("\nBuild tag: ") NETXMS_BUILD_TAG;
+         MINIDUMP_USER_STREAM us;
+         us.Type = CommentStreamW;
+         us.Buffer = (void*)comments;
+         us.BufferSize = static_cast<ULONG>(_tcslen(comments) * sizeof(TCHAR));
+
+         MINIDUMP_USER_STREAM_INFORMATION usi;
+         usi.UserStreamCount = 1;
+         usi.UserStreamArray = &us;
+
+                       MiniDumpWriteDump(hProcess, pid, hFile, 
+               static_cast<MINIDUMP_TYPE>(MiniDumpWithFullMemory | MiniDumpWithHandleData | MiniDumpWithProcessThreadData), NULL, &usi, NULL);
                        CloseHandle(hFile);
                        _tprintf(_T("INFO: Minidump created successfully\n"));
                }
@@ -179,6 +192,7 @@ static BOOL ParseCommandLine(int argc, char *argv[])
 #ifdef _WIN32
                { (char *)"check-service", 0, NULL, '!' },
                { (char *)"dump", 1, NULL, '~' },
+               { (char *)"dump-dir", 1, NULL, '@' },
                { (char *)"install", 0, NULL, 'I' },
                { (char *)"login", 1, NULL, 'L' },
                { (char *)"password", 1, NULL, 'P' },
@@ -312,6 +326,17 @@ static BOOL ParseCommandLine(int argc, char *argv[])
                        case '!':       // Check service configuration (for migration from pre-0.2.20)
                                CheckServiceConfig();
                                return FALSE;
+         case '@':
+#ifdef UNICODE
+            MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, optarg, -1, g_szDumpDir, MAX_PATH);
+#else
+            strlcpy(g_szDumpDir, optarg, MAX_PATH);
+#endif
+            if (g_szDumpDir[_tcslen(g_szDumpDir) - 1] == _T('\\'))
+            {
+               g_szDumpDir[_tcslen(g_szDumpDir) - 1] = 0;
+            }
+            break;
                        case '~':
                                CreateMiniDump(strtoul(optarg, NULL, 0));
                                return FALSE;