VirtualBox

Ignore:
Timestamp:
Aug 24, 2010 12:18:38 PM (15 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
65124
Message:

coredumper-solaris: Fixed suspend/resume threads to not use heap. Addressed the todos in r65077.

Location:
trunk/src/VBox/Runtime/r3/solaris
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Runtime/r3/solaris/coredumper-solaris.cpp

    r31869 r31914  
    116116 * @param cbToRead          Size of data to read.
    117117 *
    118  * @return VBox status code.
     118 * @return IPRT status code.
    119119 */
    120120static int ReadFileNoIntr(RTFILE hFile, void *pv, size_t cbToRead)
     
    139139 * @param cbToRead          Size of data to write.
    140140 *
    141  * @return VBox status code.
     141 * @return IPRT status code.
    142142 */
    143143static int WriteFileNoIntr(RTFILE hFile, const void *pcv, size_t cbToRead)
     
    220220 * @param pVBoxCore         Pointer to the core object.
    221221 *
    222  * @return VBox status code.
     222 * @return IPRT status code.
    223223 */
    224224static int AllocMemoryArea(PVBOXCORE pVBoxCore)
     
    339339 * @param pcb               Where to store size of the buffer.
    340340 *
    341  * @return VBox status code.
     341 * @return IPRT status code.
    342342 */
    343343static int ProcReadFileInto(PVBOXCORE pVBoxCore, const char *pszProcFileName, void **ppv, size_t *pcb)
     
    351351    if (RT_SUCCESS(rc))
    352352    {
    353         RTFileGetSize(hFile, (uint64_t *)pcb); /** @todo size_t != uint64_t! */
     353        uint64_t u64Size;
     354        RTFileGetSize(hFile, &u64Size);
     355        *pcb = u64Size < ~(size_t)0 ? u64Size : ~(size_t)0;
    354356        if (*pcb > 0)
    355357        {
     
    378380 * @param pVBoxCore         Pointer to the core object.
    379381 *
    380  * @return VBox status code.
     382 * @return IPRT status code.
    381383 */
    382384static int ProcReadInfo(PVBOXCORE pVBoxCore)
     
    406408 * @param pVBoxCore         Pointer to the core object.
    407409 *
    408  * @return VBox status code.
     410 * @return IPRT status code.
    409411 */
    410412static int ProcReadStatus(PVBOXCORE pVBoxCore)
     
    437439 *
    438440 * @remarks Should not be called before successful call to @see AllocMemoryArea()
    439  * @return VBox status code.
     441 * @return IPRT status code.
    440442 */
    441443static int ProcReadCred(PVBOXCORE pVBoxCore)
     
    454456 *
    455457 * @remarks Should not be called before successful call to @see AllocMemoryArea()
    456  * @return VBox status code.
     458 * @return IPRT status code.
    457459 */
    458460static int ProcReadPriv(PVBOXCORE pVBoxCore)
     
    480482 *
    481483 * @remarks Should not be called before successful call to @see AllocMemoryArea()
    482  * @return VBox status code.
     484 * @return IPRT status code.
    483485 */
    484486static int ProcReadLdt(PVBOXCORE pVBoxCore)
     
    497499 *
    498500 * @remarks Should not be called before successful call to @see AllocMemoryArea()
    499  * @return VBox status code.
     501 * @return IPRT status code.
    500502 */
    501503static int ProcReadAuxVecs(PVBOXCORE pVBoxCore)
     
    514516    }
    515517
    516     size_t cbAuxFile = 0;
    517     RTFileGetSize(hFile, (uint64_t *)&cbAuxFile);  /** @todo size_t != uint64_t! */
     518    uint64_t u64Size;
     519    RTFileGetSize(hFile, &u64Size);
     520    size_t cbAuxFile = u64Size < ~(size_t)0 ? u64Size : ~(size_t)0;
    518521    if (cbAuxFile >= sizeof(auxv_t))
    519522    {
     
    585588 *
    586589 * @remarks Should not be called before successful call to @see AllocMemoryArea()
    587  * @return VBox status code.
     590 * @return IPRT status code.
    588591 */
    589592static int ProcReadMappings(PVBOXCORE pVBoxCore)
     
    606609         * Allocate and read all the prmap_t objects from proc.
    607610         */
    608         size_t cbMapFile = 0;
    609         RTFileGetSize(hFile, (uint64_t *)&cbMapFile);  /** @todo size_t != uint64_t! */
     611        uint64_t u64Size;
     612        RTFileGetSize(hFile, &u64Size);
     613        size_t cbMapFile = u64Size < ~(size_t)0 ? u64Size : ~(size_t)0;
    610614        if (cbMapFile >= sizeof(prmap_t))
    611615        {
     
    716720 *
    717721 * @remarks Should not be called before successful call to @see AllocMemoryArea()
    718  * @return VBox status code.
     722 * @return IPRT status code.
    719723 */
    720724static int ProcReadThreads(PVBOXCORE pVBoxCore)
     
    876880 * @param pVBoxCore         Pointer to the core object.
    877881 *
    878  * @return VBox status code.
     882 * @return IPRT status code.
    879883 */
    880884static int ProcReadMiscInfo(PVBOXCORE pVBoxCore)
     
    10631067
    10641068
     1069/**
     1070 * Callback for rtCoreDumperForEachThread to suspend a thread.
     1071 *
     1072 * @param pVBoxCore             Pointer to the core object.
     1073 * @param pvThreadInfo          Opaque pointer to thread information.
     1074 *
     1075 * @return IPRT status code.
     1076 */
     1077static int suspendThread(PVBOXCORE pVBoxCore, void *pvThreadInfo)
     1078{
     1079    AssertPtrReturn(pvThreadInfo, VERR_INVALID_POINTER);
     1080    NOREF(pVBoxCore);
     1081
     1082    lwpsinfo_t *pThreadInfo = (lwpsinfo_t *)pvThreadInfo;
     1083    CORELOGRELSYS((CORELOG_NAME ":suspendThread %d\n", (lwpid_t)pThreadInfo->pr_lwpid));
     1084    if ((lwpid_t)pThreadInfo->pr_lwpid != pVBoxCore->VBoxProc.hCurThread)
     1085        _lwp_suspend(pThreadInfo->pr_lwpid);
     1086    return VINF_SUCCESS;
     1087}
     1088
     1089
     1090/**
     1091 * Callback for rtCoreDumperForEachThread to resume a thread.
     1092 *
     1093 * @param pVBoxCore             Pointer to the core object.
     1094 * @param pvThreadInfo          Opaque pointer to thread information.
     1095 *
     1096 * @return IPRT status code.
     1097 */
     1098static int resumeThread(PVBOXCORE pVBoxCore, void *pvThreadInfo)
     1099{
     1100    AssertPtrReturn(pvThreadInfo, VERR_INVALID_POINTER);
     1101    NOREF(pVBoxCore);
     1102
     1103    lwpsinfo_t *pThreadInfo = (lwpsinfo_t *)pvThreadInfo;
     1104    if ((lwpid_t)pThreadInfo->pr_lwpid != (lwpid_t)pVBoxCore->VBoxProc.hCurThread)
     1105        _lwp_continue(pThreadInfo->pr_lwpid);
     1106    return VINF_SUCCESS;
     1107}
     1108
     1109
     1110/**
     1111 * Calls a thread worker function for all threads in the process as described by /proc
     1112 *
     1113 * @param pVBoxCore             Pointer to the core object.
     1114 * @param pcThreads             Number of threads read.
     1115 * @param pfnWorker             Callback function for each thread.
     1116 *
     1117 * @return IPRT status code.
     1118 */
     1119static int rtCoreDumperForEachThread(PVBOXCORE pVBoxCore,  uint64_t *pcThreads, PFNCORETHREADWORKER pfnWorker)
     1120{
     1121    AssertPtrReturn(pVBoxCore, VERR_INVALID_POINTER);
     1122
     1123    PVBOXPROCESS pVBoxProc = &pVBoxCore->VBoxProc;
     1124
     1125    /*
     1126     * Read the information for threads.
     1127     * Format: prheader_t + array of lwpsinfo_t's.
     1128     */
     1129    char szLpsInfoPath[PATH_MAX];
     1130    RTStrPrintf(szLpsInfoPath, sizeof(szLpsInfoPath), "/proc/%d/lpsinfo", (int)pVBoxProc->Process);
     1131
     1132    RTFILE hFile = NIL_RTFILE;
     1133    int rc = RTFileOpen(&hFile, szLpsInfoPath, RTFILE_O_READ);
     1134    if (RT_SUCCESS(rc))
     1135    {
     1136        uint64_t u64Size;
     1137        RTFileGetSize(hFile, &u64Size);
     1138        size_t cbInfoHdrAndData = u64Size < ~(size_t)0 ? u64Size : ~(size_t)0;
     1139        void *pvInfoHdr = mmap(NULL, cbInfoHdrAndData, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1 /* fd */, 0 /* offset */);
     1140        if (pvInfoHdr)
     1141        {
     1142            rc = RTFileRead(hFile, pvInfoHdr, cbInfoHdrAndData, NULL);
     1143            if (RT_SUCCESS(rc))
     1144            {
     1145                prheader_t *pHeader = (prheader_t *)pvInfoHdr;
     1146                lwpsinfo_t *pThreadInfo = (lwpsinfo_t *)((uintptr_t)pvInfoHdr + sizeof(prheader_t));
     1147                for (unsigned i = 0; i < pHeader->pr_nent; i++)
     1148                {
     1149                    pfnWorker(pVBoxCore, pThreadInfo);
     1150                    pThreadInfo = (lwpsinfo_t *)((uintptr_t)pThreadInfo + pHeader->pr_entsize);
     1151                }
     1152                if (pcThreads)
     1153                    *pcThreads = pHeader->pr_nent;
     1154            }
     1155
     1156            munmap(pvInfoHdr, cbInfoHdrAndData);
     1157        }
     1158        else
     1159            rc = VERR_NO_MEMORY;
     1160        RTFileClose(hFile);
     1161    }
     1162
     1163    return rc;
     1164}
     1165
     1166
    10651167/**
    10661168 * Resume all threads of this process.
    10671169 *
    1068  * @param pVBoxProc         Pointer to the VBox process.
    1069  *
    1070  * @return VBox error code.
    1071  */
    1072 static int rtCoreDumperResumeThreads(PVBOXPROCESS pVBoxProc)
    1073 {
    1074     AssertReturn(pVBoxProc, VERR_INVALID_POINTER);
     1170 * @param pVBoxCore             Pointer to the core object.
     1171 *
     1172 * @return IPRT status code..
     1173 */
     1174static int rtCoreDumperResumeThreads(PVBOXCORE pVBoxCore)
     1175{
     1176    AssertReturn(pVBoxCore, VERR_INVALID_POINTER);
     1177
     1178#if 1
     1179    uint64_t cThreads;
     1180    return rtCoreDumperForEachThread(pVBoxCore, &cThreads, resumeThread);
     1181#else
     1182    PVBOXPROCESS pVBoxProc = &pVBoxCore->VBoxProc;
    10751183
    10761184    char szCurThread[128];
     
    11111219        rc = VERR_READ_ERROR;
    11121220    }
    1113 
    11141221    return rc;
    1115 }
    1116 
    1117 
    1118 /**
    1119  * Stop all running threads of this process. Before dumping any
    1120  * core we need to make sure the process is quiesced.
    1121  *
    1122  * @param pVBoxProc         Pointer to the VBox process.
    1123  *
    1124  * @return VBox error code.
    1125  */
    1126 static int rtCoreDumperSuspendThreads(PVBOXPROCESS pVBoxProc)
    1127 {
     1222#endif
     1223}
     1224
     1225
     1226/**
     1227 * Stop all running threads of this process except the current one.
     1228 *
     1229 * @param pVBoxCore         Pointer to the core object.
     1230 * 
     1231 * @return IPRT status code.
     1232 */
     1233static int rtCoreDumperSuspendThreads(PVBOXCORE pVBoxCore)
     1234{
     1235    AssertPtrReturn(pVBoxCore, VERR_INVALID_POINTER);
     1236
     1237    /*
     1238     * This function tries to ensures while we suspend threads, no newly spawned threads
     1239     * or a combination of spawning and terminating threads can cause any threads to be left running.
     1240     * The assumption here is that threads can only increase not decrease across iterations.
     1241     */
     1242#if 1
     1243    uint16_t cTries = 0;
     1244    uint64_t aThreads[4];
     1245    RT_ZERO(aThreads);
     1246    int rc = VERR_GENERAL_FAILURE;
     1247    void *pv = NULL;
     1248    size_t cb = 0;
     1249    for (cTries = 0; cTries < RT_ELEMENTS(aThreads); cTries++)
     1250    {
     1251        rc = rtCoreDumperForEachThread(pVBoxCore, &aThreads[cTries], suspendThread);
     1252        if (RT_FAILURE(rc))
     1253            break;
     1254    }
     1255    if (   RT_SUCCESS(rc)
     1256        && aThreads[cTries - 1] != aThreads[cTries - 2])
     1257    {
     1258        CORELOGRELSYS((CORELOG_NAME "rtCoreDumperSuspendThreads: possible thread bomb!?\n"));
     1259        rc = VERR_GENERAL_FAILURE;   /* @todo better error code */
     1260    }
     1261    return rc;
     1262#else
     1263    PVBOXPROCESS pVBoxProc = &pVBoxCore->VBoxProc;
     1264
    11281265    char szCurThread[128];
    11291266    char szPath[PATH_MAX];
     
    11801317
    11811318    return rc;
     1319#endif
    11821320}
    11831321
     
    12041342 * @param cb                Size of the data.
    12051343 *
    1206  * @return VBox status code.
     1344 * @return IPRT status code.
    12071345 */
    12081346static int ElfWriteNoteHeader(PVBOXCORE pVBoxCore, uint_t Type, const void *pcv, size_t cb)
     
    13281466 * @param enmType           Type of core file information required.
    13291467 *
    1330  * @return VBox status code.
     1468 * @return IPRT status code.
    13311469 */
    13321470static int ElfWriteNoteSection(PVBOXCORE pVBoxCore, VBOXSOLCORETYPE enmType)
     
    14711609 * @param pVBoxCore         Pointer to the core object.
    14721610 *
    1473  * @return VBox status code.
     1611 * @return IPRT status code.
    14741612 */
    14751613static int ElfWriteMappings(PVBOXCORE pVBoxCore)
     
    15311669 * @param pVBoxCore         Pointer to the core object.
    15321670 *
    1533  * @return VBox status code.
     1671 * @return IPRT status code.
    15341672 */
    15351673static int ElfWriteMappingHeaders(PVBOXCORE pVBoxCore)
     
    17461884    }
    17471885
    1748     rtCoreDumperResumeThreads(pVBoxProc);
     1886    rtCoreDumperResumeThreads(pVBoxCore);
    17491887    return rc;
    17501888}
     
    17601898 *
    17611899 * @remarks Halts all threads.
    1762  * @return VBox status code.
     1900 * @return IPRT status code.
    17631901 */
    17641902static int rtCoreDumperCreateCore(PVBOXCORE pVBoxCore, ucontext_t *pContext)
     
    18061944     * Quiesce the process.
    18071945     */
    1808     int rc = rtCoreDumperSuspendThreads(pVBoxProc);
     1946    int rc = rtCoreDumperSuspendThreads(pVBoxCore);
    18091947    if (RT_SUCCESS(rc))
    18101948    {
     
    18772015         * Resume threads on failure.
    18782016         */
    1879         rtCoreDumperResumeThreads(pVBoxProc);
     2017        rtCoreDumperResumeThreads(pVBoxCore);
    18802018    }
    18812019    else
     
    18912029 * @param pVBoxCore         Pointer to the core object.
    18922030 *
    1893  * @return VBox status code.
     2031 * @return IPRT status code.
    18942032 */
    18952033static int rtCoreDumperDestroyCore(PVBOXCORE pVBoxCore)
     
    19102048 *
    19112049 * @param   pContext            The context of the caller.
    1912  * @returns VBox status code.
     2050 * @returns IPRT status code.
    19132051 */
    19142052static int rtCoreDumperTakeDump(ucontext_t *pContext)
     
    19322070        rc = rtCoreDumperWriteCore(&VBoxCore, &WriteFileNoIntr);
    19332071        if (RT_SUCCESS(rc))
    1934             CORELOGRELSYS((CORELOG_NAME "Success! Core written to %s\n", VBoxCore.szCorePath));
     2072            CORELOGRELSYS((CORELOG_NAME "Core dumped in %s\n", VBoxCore.szCorePath));
    19352073        else
    19362074            CORELOGRELSYS((CORELOG_NAME "TakeDump: WriteCore failed. szCorePath=%s rc=%Rrc\n", VBoxCore.szCorePath, rc));
  • trunk/src/VBox/Runtime/r3/solaris/coredumper-solaris.h

    r31862 r31914  
    166166
    167167typedef int (*PFNCOREACCUMULATOR)(PVBOXCORE pVBoxCore);
     168typedef int (*PFNCORETHREADWORKER)(PVBOXCORE pVBoxCore, void *pvThreadInfo);
    168169
Note: See TracChangeset for help on using the changeset viewer.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette