Пример #1
0
void _LogFooter(void)
{
    char   szLibPath [ PS_MAX_PATH ];
#if defined (WIN32)
    GetModuleFileNameA(NULL, szLibPath, PS_MAX_PATH);
#elif defined (_LINUX)

    if (program_invocation_name[0] == '/')
    {
        // file contains full path already, so don't append path
        sprintf_s(szLibPath, PS_MAX_PATH, "%s", program_invocation_name);
    }
    else
    {
        char currentDir[PS_MAX_PATH];
        getcwd(currentDir, PS_MAX_PATH);
        sprintf_s(szLibPath, PS_MAX_PATH, "%s/%s", currentDir, program_invocation_name);
    }

#endif
    _Log(logRAW,  "App : %s\n", szLibPath);
    _Log(logRAW,  "PID: %i\n", osGetCurrentProcessId());
    _Log(logRAW,  "Time: %s\n", GetTimeStr().asCharArray());
    _Log(logRAW, "--------------THE END------------------\n");
}
//--------------------------------------------------------------------------
/// Generate a trace info block that can be appended to the top of the trace. Included application and system information.
/// \param outHeaderString A string containing the generated block of header text.
/// \returns True if the header was generated successfully. False if it failed.
//--------------------------------------------------------------------------
bool MultithreadedTraceAnalyzerLayer::GenerateLinkedTraceHeader(gtASCIIString& outHeaderString)
{
    bool bHeaderGenerated = false;

    // The response should include a header when connected to CodeXL Graphics.
    outHeaderString.appendFormattedString("//CodeXL Frame Trace\n");

    osModuleArchitecture moduleArchitecture;
    osRuntimePlatform currentPlatform;
    gtString executablePath;
    gtString commandLine;
    gtString workingDirectory;

    if (osGetProcessLaunchInfo(osGetCurrentProcessId(), moduleArchitecture, currentPlatform, executablePath, commandLine, workingDirectory) == true)
    {
        outHeaderString.appendFormattedString("//ProcessExe=%s\n", executablePath.asASCIICharArray());

        // Build a timestamp.
        osTime currentTime;
        currentTime.setFromCurrentTime();
        tm timeStruct;
        currentTime.timeAsTmStruct(timeStruct, osTime::LOCAL);

        // Need to add 1900, since tm contains "years since 1900".
        int year = timeStruct.tm_year + 1900;

        // Need to add 1, since tm contains "months since January".
        int month = timeStruct.tm_mon + 1;

        int day = timeStruct.tm_mday;
        int hour = timeStruct.tm_hour;
        int minute = timeStruct.tm_min;
        int second = timeStruct.tm_sec;

        gtASCIIString timestampBuilder;
        timestampBuilder.appendFormattedString("%d/%d/%d %d:%d:%d", month, day, year, hour, minute, second);
        outHeaderString.appendFormattedString("//TraceDateTime=%s\n", timestampBuilder.asCharArray());

        outHeaderString.appendFormattedString("//TraceFileVersion=%d\n", 1);
        outHeaderString.appendFormattedString("//ApplicationArgs=%s\n", commandLine.asASCIICharArray());
        outHeaderString.appendFormattedString("//WorkingDirectory=%s\n", workingDirectory.asASCIICharArray());

        // Build a system information header string.
        std::string systemInfo;
        OSWrappers::WriteSystemInfoString(systemInfo);
        outHeaderString.appendFormattedString("\n%s\n", systemInfo.c_str());

        bHeaderGenerated = true;
    }
    else
    {
        Log(logERROR, "Failed to retrieve process info when building response header.\n");
    }

    return bHeaderGenerated;
}
//-----------------------------------------------------------------------------
/// InitCommunication
///
/// This function only needs to be called by wrapper plugins. It sets up the
/// inter-process communication between the wrapper (which is in the app's
/// process space) and the PerfServer.
//-----------------------------------------------------------------------------
bool InitCommunication(const char* strShortDescription, ProcessRequest_type pProcessRequestCallback)
{
    unsigned long pid = osGetCurrentProcessId();
#ifdef _WIN32
    sprintf_s(g_strSharedMemoryName, PS_MAX_PATH, "%lu/%s", pid, strShortDescription);
#else
    // the '/' character can't be used as a filename in Linux, so just use the plugin name as the shared memory name
    // (ignore the process ID)
    sprintf_s(g_strSharedMemoryName, PS_MAX_PATH, "%lu %s", pid, strShortDescription);
#endif

    if (smCreate(g_strSharedMemoryName, 100, sizeof(HTTPRequestHeader)) == false)
    {
        Log(logERROR, "InitCommunication: Can't open or create SharedMemory for %s.\n", strShortDescription);
        return false;
    }

    if (smOpen("PLUGINS_TO_GPS") == false)
    {
        smClose(g_strSharedMemoryName);
        Log(logERROR, "InitCommunication: Can't open SharedMemory for PLUGINS_TO_GPS.\n");
        return false;
    }

    // store a local pointer to the ProcessRequest function
    g_processRequest = pProcessRequestCallback;

    if (g_processRequest == NULL)
    {
        smClose(g_strSharedMemoryName);
        Log(logERROR, "InitCommunication: ProcessRequest is NULL\n");
        return false;
    }

    // protect the maps from being changed by other threads using the mutex
    ScopeLock lock(s_mutex);

    g_requestMap.clear();
    g_pBufferedResponse = NULL;
    g_uBufferedResponseSize = 0;

    return true;
}
//--------------------------------------------------------------------------
/// Handle what happens when a Linked Trace is requested. We can either:
/// 1. Return the trace response as normal.
/// 2. Cache the response to disk, and generate a "trace metadata" file used to retrieve the trace later.
/// \param inFullResponseString The response string built by tracing the application.
/// \param inbSaveResponseToFile A switch used to determine which response method to use.
//--------------------------------------------------------------------------
void MultithreadedTraceAnalyzerLayer::HandleLinkedTraceResponse(std::stringstream& inFullResponseString, bool inbSaveResponseToFile)
{
    // If we're building for use with CodeXL, insert extra metadata into the response before returning.
#if defined(CODEXL_GRAPHICS)
    // The response should include a header when connected to CodeXL Graphics.
    gtASCIIString headerBuilder;
    headerBuilder.appendFormattedString("//AMD CodeXL Frame Trace\n");

    osModuleArchitecture moduleArchitecture;
    osRuntimePlatform currentPlatform;
    gtString executablePath;
    gtString commandLine;
    gtString workingDirectory;

    if (osGetProcessLaunchInfo(osGetCurrentProcessId(), moduleArchitecture, currentPlatform, executablePath, commandLine, workingDirectory) == true)
    {
        headerBuilder.appendFormattedString("//ProcessExe=%s\n", executablePath.asASCIICharArray());

        // Build a timestamp.
        osTime currentTime;
        currentTime.setFromCurrentTime();
        tm timeStruct;
        currentTime.timeAsTmStruct(timeStruct, osTime::LOCAL);

        // Need to add 1900, since tm contains "years since 1900".
        int year = timeStruct.tm_year + 1900;

        // Need to add 1, since tm contains "months since January".
        int month = timeStruct.tm_mon + 1;

        int day = timeStruct.tm_mday;
        int hour = timeStruct.tm_hour;
        int minute = timeStruct.tm_min;
        int second = timeStruct.tm_sec;

        gtASCIIString timestampBuilder;
        timestampBuilder.appendFormattedString("%d/%d/%d %d:%d:%d", month, day, year, hour, minute, second);
        headerBuilder.appendFormattedString("//TraceDateTime=%s\n", timestampBuilder.asCharArray());

        headerBuilder.appendFormattedString("//TraceFileVersion=%d\n", 1);
        headerBuilder.appendFormattedString("//ApplicationArgs=%s\n", commandLine.asASCIICharArray());
        headerBuilder.appendFormattedString("//WorkingDirectory=%s\n", workingDirectory.asASCIICharArray());
    }
    else
    {
        Log(logERROR, "Failed to retrieve process info when building response header.\n");
    }

    // Build a system information header string.
    std::string systemInfo;
    OSWrappers::WriteSystemInfoString(systemInfo);
    headerBuilder.appendFormattedString("\n%s\n", systemInfo.c_str());

    // Store the response temporarily.
    std::string headerString = headerBuilder.asCharArray();
    std::string responseString = inFullResponseString.str();

    // Clear the response string stream.
    inFullResponseString.str(std::string());
    inFullResponseString.clear();

    // Write the header and response chunks into the final response.
    inFullResponseString << headerString;
    inFullResponseString << responseString;
#endif

    // Check if we want to cache the response to disk, or return it as-is.
    if (inbSaveResponseToFile)
    {
        std::string metadataXMLString;
        bool bWriteMetadataSuccessful = WriteTraceAndMetadataFiles(inFullResponseString, metadataXMLString);
        if (bWriteMetadataSuccessful)
        {
            // Send a response back to the client indicating which trace metadata file was written to disk.
            mCmdLinkedTraceWithSave.Send(metadataXMLString.c_str());
        }
        else
        {
            Log(logERROR, "Failed to write trace metadata XML.\n");
            mCmdLinkedTraceWithSave.Send("Failed");
        }
    }
    else
    {
        // Return the normal trace response string.
        // Send a response containing the API and GPU trace text.
        mCmdLinkedTrace.Send(std::string(inFullResponseString.str()).c_str());
    }
}
//--------------------------------------------------------------------------
/// Write a trace's metadata file and return the contenst through the out-param.
/// \param inFullResponseString The full response string for a collected linked trace request.
/// \param outMetadataXML The XML metadata string to return to the client.
/// \returns True if writing the metadata file was successful.
//--------------------------------------------------------------------------
bool MultithreadedTraceAnalyzerLayer::WriteTraceAndMetadataFiles(const std::stringstream& inFullResponseString, std::string& outMetadataXML)
{
    bool bWrittenSuccessfully = false;

    // Empty out the incoming path to the metadata file. We'll know the exact path later.
    outMetadataXML.assign("");

    osModuleArchitecture moduleArchitecture;
    osRuntimePlatform currentPlatform;
    gtString executablePath;
    gtString commandLine;
    gtString workingDirectory;

    // Retrieve the name of the instrumented application. Construct a metadata filename which references it.
    if (osGetProcessLaunchInfo(osGetCurrentProcessId(), moduleArchitecture, currentPlatform, executablePath, commandLine, workingDirectory) == true)
    {
        osFilePath executableFilepath;
        executableFilepath.setFullPathFromString(executablePath);

        gtString appName;
        if (executableFilepath.getFileName(appName) == true)
        {
            osTime currentTime;
            currentTime.setFromCurrentTime();
            tm timeStruct;
            currentTime.timeAsTmStruct(timeStruct, osTime::LOCAL);

            // Need to add 1900, since tm contains "years since 1900".
            int year = timeStruct.tm_year + 1900;

            // Need to add 1, since tm contains "months since January".
            int month = timeStruct.tm_mon + 1;
            int day = timeStruct.tm_mday;

            int hour = timeStruct.tm_hour;
            int minute = timeStruct.tm_min;
            int second = timeStruct.tm_sec;

            gtASCIIString metadataFilename;

            // ExecutableFilename-YEAR-MM-DD-HOUR-MINUTE-SECOND
            metadataFilename.appendFormattedString("description-%s-%d-%d-%d-%d-%d-%d.xml",
                appName.asASCIICharArray(),
                year, month, day,
                hour, minute, second);

            // Build a path to the GPS folder within the Temp directory.
            osFilePath systemTempDirectory;
            systemTempDirectory.setPath(osFilePath::OS_TEMP_DIRECTORY);


            gtString toolDirectory;
#ifdef CODEXL_GRAPHICS
            toolDirectory.fromASCIIString("CodeXL");
#else
            toolDirectory.fromASCIIString(GetPerfStudioDirName());
#endif
            // @TODO: Construct a path from the temp + tool directory.
            systemTempDirectory.appendSubDirectory(toolDirectory);

            gtList<osFilePath> toolDirectoryPaths;
            osDirectory d;
            d.setDirectoryPath(systemTempDirectory);

            // @TODO: Find a better way to create the "Session" directory. We shouldn't need to search through existing session directories.
            int maxSessionIndex = 0;
            bool bGotSubDirectories = d.getSubDirectoriesPaths(osDirectory::SORT_BY_NAME_DESCENDING, toolDirectoryPaths);
            if (bGotSubDirectories)
            {
                // Step through each directory, and look for "Session" folders.
                gtList<osFilePath>::iterator subdirectoryIter;
                for (subdirectoryIter = toolDirectoryPaths.begin(); subdirectoryIter != toolDirectoryPaths.end(); ++subdirectoryIter)
                {
                    gtString subdirString;
                    osFilePath subdir = *subdirectoryIter;
                    subdir.getFileName(subdirString);

                    if (subdir.isDirectory() && subdirString.startsWith(L"Session"))
                    {
                        // Remove the "Session" part of the string. We're only interested in the number at the end.
                        subdirString.replace(L"Session", L"", true);

                        const char* sessionIndexAsString = subdirString.asASCIICharArray();
                        int thisSessionId = atoi(sessionIndexAsString);

                        if (thisSessionId > maxSessionIndex)
                        {
                            maxSessionIndex = thisSessionId;
                        }
                    }

                }
            }


            gtASCIIString pathToDataDirectory = systemTempDirectory.asString().asASCIICharArray();

            // Metadata files will be saved to the temp directory with the following filename scheme:
            // "%TEMP%/ToolDirectory/Session[Index]/ApplicationBinaryName/Frame[Index]/description.xml"

            int frameIndex = GetInterceptor()->GetParentLayerManager()->GetFrameCount();

            // Generate a "Session" folder with a number at the end. Compute the correct number by looking at the
            // Session folders that already exist
            gtASCIIString sessionString;
            sessionString.appendFormattedString("Session%d", maxSessionIndex + 1);

            pathToDataDirectory.appendFormattedString("\\%s\\%s\\Frame%d\\", sessionString.asCharArray(), appName.asASCIICharArray(), frameIndex);

            // Create the data directory if it doesn't already exist.
            gtString fullPathToDataDirectoryAsGTString;
            fullPathToDataDirectoryAsGTString.fromASCIIString(pathToDataDirectory.asCharArray());

            osDirectory dir;
            dir.setDirectoryFullPathFromString(fullPathToDataDirectoryAsGTString);
            if (!dir.exists())
            {
                bool bDirectoryCreated = dir.create();
                if (!bDirectoryCreated)
                {
                    Log(logERROR, "Failed to create data directory for traced frame: '%s'.\n", fullPathToDataDirectoryAsGTString.asASCIICharArray());
                }
            }

            gtASCIIString pathToMetadataFile = pathToDataDirectory;
            pathToMetadataFile.appendFormattedString("%s", metadataFilename.asCharArray());

            gtString fullMetadataFilepathAsGTString;
            fullMetadataFilepathAsGTString.fromASCIIString(pathToMetadataFile.asCharArray());

            osFile metadataFile(fullMetadataFilepathAsGTString);
            bool bMetadataFileOpened = metadataFile.open(osChannel::OS_ASCII_TEXT_CHANNEL, osFile::OS_OPEN_TO_WRITE);

            // If we've successfully opened the metadata file, we'll also attempt to write the trace file.
            if (bMetadataFileOpened)
            {
                osFilePath traceFileDirectory;
                traceFileDirectory.setPath(osFilePath::OS_TEMP_DIRECTORY);

                traceFileDirectory.appendSubDirectory(toolDirectory);

                // Construct a filename for the cached trace response.
                gtASCIIString fullTraceFilename;
                fullTraceFilename.appendFormattedString("LinkedTrace-%s-%d-%d-%d-%d-%d-%d.ltr", appName.asASCIICharArray(), year, month, day, hour, minute, second);

                gtASCIIString fullTraceFilePath = pathToDataDirectory;
                fullTraceFilePath.appendFormattedString("%s", fullTraceFilename.asCharArray());

                gtString fullTraceResponseFilepathGTString;
                fullTraceResponseFilepathGTString.fromASCIIString(fullTraceFilePath.asCharArray());

                // Write the contents of the trace response file.
                osFile traceResponseFile(fullTraceResponseFilepathGTString);
                bool bTraceResponseFileOpened = traceResponseFile.open(osChannel::OS_ASCII_TEXT_CHANNEL, osFile::OS_OPEN_TO_WRITE);
                if (bTraceResponseFileOpened)
                {
                    // Dump the response into an ASCII string.
                    std::string responseAsString = inFullResponseString.str();

                    // Now put the ASCII string into a gtString so we can write it to the open file.
                    gtString gtStringResponse;
                    std::wstring wideString;
                    wideString.assign(responseAsString.begin(), responseAsString.end());
                    gtStringResponse.appendFormattedString(L"%s", wideString.c_str());
                    traceResponseFile.writeString(gtStringResponse);
                    traceResponseFile.close();
                }
                else
                {
                    Log(logERROR, "Failed to write trace response to file: '%s'\n", fullTraceResponseFilepathGTString.asASCIICharArray());
                }

                // Write the filename for the associated trace response that was just collected.
                std::string traceFilepathAsString;
                traceFilepathAsString.assign(fullTraceResponseFilepathGTString.asASCIICharArray());

                TraceMetadata metadata;

                // Insert the location of the metadata file being written out.
                metadata.mMetadataFilepath = pathToMetadataFile.asCharArray();

                // Insert the path to the cached trace file.
                metadata.mPathToTraceFile = fullTraceFilePath.asCharArray();

                // @TODO: When we have a framebuffer image system working, assign the path-to-image here.
                metadata.mPathToFrameBufferImage = "UNKNOWNPATH";

                ModernAPILayerManager* layerManager = GetInterceptor()->GetParentLayerManager();

                FrameInfo frameInfo;

                layerManager->GetFrameInfo(frameInfo);

                // Populate the metadata structure with the values stored in the LayerManager.
                metadata.mFrameInfo = frameInfo;
                metadata.mFrameIndex = frameIndex;
                metadata.mArchitecture = moduleArchitecture;

                // Write the metadata xml into the output file.
                gtASCIIString metadataXMLString;
                metadata.WriteToXML(metadataXMLString);
                gtString metadataXMLAsGTString;
                metadataXMLAsGTString.fromASCIIString(metadataXMLString.asCharArray());

                // Write the metadata XML into the file, and close.
                metadataFile.writeString(metadataXMLAsGTString);
                metadataFile.close();

                // The client will receive the full metadata XML string to parse.
                outMetadataXML.assign(metadataXMLString.asCharArray());

                bWrittenSuccessfully = true;
            }
            else
            {
                Log(logERROR, "Failed to open trace metadata file for writing: '%s'\n", metadataFilename);
            }
        }
        else
        {
            Log(logERROR, "Failed to retrieve the instrumented process's application filename.\n");
        }
    }
    else
    {
        Log(logERROR, "Failed to retrieve process launch info for target application.\n");
    }

    return bWrittenSuccessfully;
}
Пример #6
0
//--------------------------------------------------------------------------
/// The layer must create its resources here, it may hook some functions if really needed
/// \param type the creation object type.
/// \param pPtr Pointer to the object that was just created.
/// \return True if success, False if fail.
//--------------------------------------------------------------------------
bool ModernAPILayerManager::OnCreate(CREATION_TYPE type, void* pPtr)
{
    bool bReturn = true;

    for (UINT32 i = 0; i < m_AvailableLayers.size(); i++)
    {
        if (m_AvailableLayers[i]->OnCreate(type, pPtr) == false)
        {
            Log(logERROR, "Layer with index '%u' failed in OnCreate call.\n", i);
            bReturn = false;
        }
    }

    static bool bInitialized = false;

    if (!bInitialized)
    {
        osModuleArchitecture moduleArchitecture;
        osRuntimePlatform currentPlatform;
        gtString executablePathString;
        gtString commandLine;
        gtString workingDirectory;

        if (osGetProcessLaunchInfo(osGetCurrentProcessId(), moduleArchitecture, currentPlatform, executablePathString, commandLine, workingDirectory) == true)
        {
            osFilePath executablePath;
            executablePath.setFullPathFromString(executablePathString);

            gtString appName;

            if (executablePath.getFileName(appName) == true)
            {
                gtString capturePlayerExecutableName;
#ifdef CODEXL_GRAPHICS
                capturePlayerExecutableName.fromASCIIString("CXLGraphicsServerPlayer");
#else // CODEXL_GRAPHICS
                capturePlayerExecutableName.fromASCIIString("CapturePlayer");
#endif // CODEXL_GRAPHICS

                if (appName.startsWith(capturePlayerExecutableName))
                {
                    mbInCapturePlayer = true;
#ifdef _LINUX
                    // strip off the executable name and its path from the command line if it exists, and remove leading and trailing whitespaces
                    int startPos = commandLine.find(capturePlayerExecutableName);
                    startPos += capturePlayerExecutableName.length();
                    int endPos = commandLine.length();

                    commandLine.truncate(startPos, endPos);
                    commandLine.trim();
#endif

                    ParseCommandLine(commandLine.asASCIICharArray());
                }
            }
            else
            {
                Log(logWARNING, "Failed to parse target application filepath.\n");
            }
        }
        else
        {
            Log(logERROR, "Failed to retrieve process launch information.\n");
        }

        bInitialized = true;
    }

    return bReturn;
}
Пример #7
0
// Generate a composite log message - then finally send to handler to write and/or display
void _Log(enum LogType type, const char* fmt, ...)
{
    // check to see if logging of the level is enabled, or if s_LogConsole is specified
    // if not, don't process it.
    int logLevel = SG_GET_INT(OptionLogLevel);

    if (((type - logERROR) > logLevel && s_LogConsole == false))
    {
        return;
    }

    // Define buffer to store maximum current log message.
    // Different destinations will receive a subset of this string.
    // On Win32 the entire string is passed to OutputDebugString()

    char fullString[PS_LOG_MAX_LENGTH] = "";
    int nLen = 0;
    int nSize;
    bool truncated = false;

    char* pLogString; // String to print to logfile
    char* pConsole;   // String to print to console doesn't include debug information
    char* pRaw;       // Raw string passed in without any additional decoration

    if (truncated == false)
    {
        // Prepend "PerfStudio: " for windows OutputDebugString() messages
        nSize = _snprintf_s(&fullString[nLen], PS_LOG_MAX_LENGTH - nLen, _TRUNCATE, "PerfStudio: ");

        if ((truncated = (nSize == -1)) == false)
        {
            nLen += nSize;
        }
    }

    pLogString = &fullString[nLen]; // logfile message doesn't include above WIN32 section

#if (defined PS_LOG_DEBUG) && (defined _DEBUG)

    if (truncated == false)
    {
        // In debug builds, include the __FILE__, __LINE__ and __FUNCTION__ information
        nSize = _snprintf_s(&fullString[nLen], PS_LOG_MAX_LENGTH - nLen, _TRUNCATE, "%s(%d) : %s(): ", s_LogFile, s_LogLine, s_LogFunction);

        if ((truncated = (nSize == -1)) == false)
        {
            nLen += nSize;
        }
    }

#endif

    // Prepend accurate timestamp
    if (truncated == false)
    {
        gtASCIIString time = GetMicroTimeStr();
        time = time.substr(12);
        nSize = _snprintf_s(&fullString[nLen], PS_LOG_MAX_LENGTH - nLen, _TRUNCATE, "%-14s: ", time.asCharArray());

        if ((truncated = (nSize == -1)) == false)
        {
            nLen += nSize;
        }
    }

    pConsole = &fullString[nLen];  // String to print to console starts here

    if (truncated == false)
    {
        // Add the message type string
        switch (type)
        {
            case logERROR:
                nSize = _snprintf_s(&fullString[nLen], PS_LOG_MAX_LENGTH - nLen, _TRUNCATE, "Error:   ");
                break;

            case logWARNING:
                nSize = _snprintf_s(&fullString[nLen], PS_LOG_MAX_LENGTH - nLen, _TRUNCATE, "Warning: ");
                break;

            case logMESSAGE:
                nSize = _snprintf_s(&fullString[nLen], PS_LOG_MAX_LENGTH - nLen, _TRUNCATE, "Message: ");
                break;

            case logTRACE:
                nSize = _snprintf_s(&fullString[nLen], PS_LOG_MAX_LENGTH - nLen, _TRUNCATE, "Trace:   ");
                break;

            case logASSERT:
                nSize = _snprintf_s(&fullString[nLen], PS_LOG_MAX_LENGTH - nLen, _TRUNCATE, "Assert:  ");
                break;

            case logDEBUG:
                nSize = _snprintf_s(&fullString[nLen], PS_LOG_MAX_LENGTH - nLen, _TRUNCATE, "Debug:   ");
                break;

            case logRAW:
                // Skip
                nSize = 0;
                break;

            default:
                nSize = _snprintf_s(&fullString[nLen], PS_LOG_MAX_LENGTH - nLen, _TRUNCATE, "Unknown: ");
                break;
        }

        if ((truncated = (nSize == -1)) == false)
        {
            nLen += nSize;
        }
    }

    // Add the module identifier
    if (s_LogModule  && (truncated == false))
    {
        nSize = _snprintf_s(&fullString[nLen], PS_LOG_MAX_LENGTH - nLen, _TRUNCATE, "PID: %10u TID: %10u %-14s: ", osGetCurrentProcessId(), osGetCurrentThreadId(), s_LogModule);

        if ((truncated = (nSize == -1)) == false)
        {
            nLen += nSize;
        }
    }

    if (truncated == false)
    {
        if (SG_GET_INT(OptionLogLevel) >= logTRACE - logERROR)
        {
            // Add the indent
            for (int i = 0; (i < logIndent) && (nLen < PS_LOG_MAX_LENGTH - 1); i++, nLen++)
            {
                fullString[nLen] = ' ';
            }

            fullString[nLen] = 0;  // Ensure string in buffer remains null terminated
            truncated = (nLen == PS_LOG_MAX_LENGTH - 1);
        }
    }

    pRaw = &fullString[nLen];  // Raw undecorated string starts here

    // Add the actual Log Message
    if (truncated == false)
    {
        va_list arg_ptr;
        va_start(arg_ptr, fmt);

        nSize = vsnprintf_s(&fullString[nLen], PS_LOG_MAX_LENGTH - nLen, _TRUNCATE, fmt, arg_ptr);

        if ((truncated = (nSize == -1)) == false)
        {
            nLen += nSize;
        }

        va_end(arg_ptr);
    }

    // Check if message has been truncated and clean up accordingly

    if (truncated == true)
    {
        // Truncation occurred - change end of line to reflect this
        char truncationString[] = " ... \n";
        sprintf_s(&fullString[PS_LOG_MAX_LENGTH - sizeof(truncationString)], sizeof(truncationString), "%s", truncationString);
    }

    // Message Constructed. Print to Log, Console, and OutputDebugString as necessary
    if (type == logRAW)
    {
        if (s_LogConsole)
        {
            // Send string to console
            printf("%s", pRaw);
        }

        _logWrite(pRaw);
    }
    else
    {
        if (s_LogConsole)
        {
            // Console messages are always printed in console and in log file
            // regardless of logLEVEL
            printf("%s", pConsole);
            _logWrite(pLogString);
            OutputDebugString(fullString);
        }
        else
        {
            // not a console message - filter based on log level
            if ((type - logERROR) <= SG_GET_INT(OptionLogLevel))
            {
                if (type == logTRACE)
                {
                    // Trace messages also go to the console
                    printf("%s", pConsole);
                }

                _logWrite(pLogString);
                OutputDebugString(fullString);
            }
        }
    }
}
Пример #8
0
//-----------------------------------------------------------------------------
/// Put up a dialog box to give the user time to attach a debugger to the
/// application rather than the perf studio app.
/// \param serverName the name of the server plugin loaded into the target
/// application
/// \param initialized has the server plugin been initialized
/// \return 0 if successful, non-zero on error
//-----------------------------------------------------------------------------
int ServerUtils::CheckForDebuggerAttach(const char* serverName, bool initialized)
{
    char commandString[1024];
    int retVal = 0;

    static bool alreadyChecked = false;  // only pause application once.
    static const char fmtString[] = "The application has been paused to allow GDB to be attached to the process.\nApplication name: %s\nOpen a terminal and cd to where the %s.so is running from\n(so that gdb can load debug symbols). Use:\n\nsudo gdb attach %d\n\nPress OK to continue";
    char message[sizeof(fmtString) + 10 + PS_MAX_PATH];    // Add extra bytes for process ID

    if (SG_GET_BOOL(OptionBreak) && !alreadyChecked && initialized)         // did we run PerfServer with --break option
    {
        alreadyChecked = true;
        sprintf_s(message, sizeof(message), fmtString, program_invocation_short_name, serverName, osGetCurrentProcessId());
        sprintf(commandString, "xmessage \"%s\" -center -buttons OK", message);
        retVal = system(commandString);
    }

    return retVal;
}