diff --git a/CodeXL/Components/Graphics/Server/Common/HTTPRequest.cpp b/CodeXL/Components/Graphics/Server/Common/HTTPRequest.cpp index cb0b54366..55501e317 100755 --- a/CodeXL/Components/Graphics/Server/Common/HTTPRequest.cpp +++ b/CodeXL/Components/Graphics/Server/Common/HTTPRequest.cpp @@ -549,7 +549,7 @@ bool HTTPRequestHeader::CheckProcessStillRunning() { char* ptr = this->GetUrl(); char* sCmd = &ptr[1]; - bool isAlive = false; + bool isAlive = true; gtASCIIString str(sCmd); @@ -561,9 +561,14 @@ bool HTTPRequestHeader::CheckProcessStillRunning() str.truncate(0, end - 1); processID = atoi(str.asCharArray()); + Log(logMESSAGE, "HTTPRequestHeader::CheckProcessStillRunning: processID = %d\n", processID); + + if (processID > 0) + { // check to see if process is still running osIsProcessAlive((DWORD)processID, isAlive); } + } return isAlive; } diff --git a/CodeXL/Components/Graphics/Server/WebServer/PluginResponseThread.cpp b/CodeXL/Components/Graphics/Server/WebServer/PluginResponseThread.cpp index ec2c107db..ee0079811 100755 --- a/CodeXL/Components/Graphics/Server/WebServer/PluginResponseThread.cpp +++ b/CodeXL/Components/Graphics/Server/WebServer/PluginResponseThread.cpp @@ -72,9 +72,12 @@ void PluginResponseThread::WaitForPluginResponses(void* pData) NetSocket* client_socket = ProcessTracker::Instance()->GetSocketFromHandle(requestID); ProcessTracker::Instance()->RemoveSocketFromMap(requestID); +#ifdef CODEXL_GRAPHICS +#ifdef USE_GRAPHICS_SERVER_STATUS_RETURN_CODES // We can remove this message from the DB as we no longer need to monitor it anymore - //RequestsInFlightDatabase::Instance()->Remove(client_socket); - + RequestsInFlightDatabase::Instance()->Remove(client_socket); +#endif +#endif // now try to get the mime type if (smGet("PLUGINS_TO_GPS", &pcMimeType, PS_MAX_PATH) > 0) { diff --git a/CodeXL/Components/Graphics/Server/WebServer/ProcessTracker.cpp b/CodeXL/Components/Graphics/Server/WebServer/ProcessTracker.cpp index 951a77713..577ac2b79 100755 --- a/CodeXL/Components/Graphics/Server/WebServer/ProcessTracker.cpp +++ b/CodeXL/Components/Graphics/Server/WebServer/ProcessTracker.cpp @@ -176,7 +176,7 @@ gtASCIIString ProcessTracker::GetProcessesXML() /// \param pRequestHeader The request header. /// \param client_socket The socket used for the request ////////////////////////////////////////////////////////////////////////////////////////////////////////// -static void HandleServerStatusResponse(GRAPHICS_SERVER_STATE serverState, HTTPRequestHeader* pRequestHeader, NetSocket* client_socket) +void ProcessTracker::HandleServerStatusResponse(GRAPHICS_SERVER_STATE serverState, HTTPRequestHeader* pRequestHeader, NetSocket* client_socket) { char* strResquest = pRequestHeader->GetUrl(); @@ -1045,12 +1045,16 @@ bool ProcessTracker::PassRequestToPlugin(const char* strDestination, pRequestHeader->SetPostDataSize(0); } +#ifdef CODEXL_GRAPHICS +#ifdef USE_GRAPHICS_SERVER_STATUS_RETURN_CODES // Create a new record of this request // We will check to see when it comes back from the server. - //RequestInFlight* pNewRequest = new RequestInFlight(pRequestHeader, pClientSocket); + RequestInFlight* pNewRequest = new RequestInFlight(pRequestHeader, pClientSocket, pid); // Add the new record to the DB. - //RequestsInFlightDatabase::Instance()->Add(pClientSocket, pNewRequest); + RequestsInFlightDatabase::Instance()->Add(pClientSocket, pNewRequest); +#endif +#endif bResult = smPut(strDestination, pRequestHeader->GetHeaderData(), sizeof(HTTPHeaderData)); diff --git a/CodeXL/Components/Graphics/Server/WebServer/ProcessTracker.h b/CodeXL/Components/Graphics/Server/WebServer/ProcessTracker.h index e4ea5e18e..476e0dbd3 100755 --- a/CodeXL/Components/Graphics/Server/WebServer/ProcessTracker.h +++ b/CodeXL/Components/Graphics/Server/WebServer/ProcessTracker.h @@ -144,6 +144,12 @@ class ProcessTracker : public TSingleton< ProcessTracker > /// \return socket corresponding to the handle NetSocket* GetSocketFromHandle(CommunicationID handle); + /// Used to send a server status message back to the requesting command. + /// \param serverState The server state type to return + /// \param pRequestHeader The requesting HTTP command + /// \param client_socket The socket to communicate over + void HandleServerStatusResponse(GRAPHICS_SERVER_STATE serverState, HTTPRequestHeader* pRequestHeader, NetSocket* client_socket); + protected: /// Prevents default instances of the ProcessTracker class. diff --git a/CodeXL/Components/Graphics/Server/WebServer/RenderStallThread.cpp b/CodeXL/Components/Graphics/Server/WebServer/RenderStallThread.cpp index 3164ca33c..05bdc895b 100755 --- a/CodeXL/Components/Graphics/Server/WebServer/RenderStallThread.cpp +++ b/CodeXL/Components/Graphics/Server/WebServer/RenderStallThread.cpp @@ -9,6 +9,7 @@ #include "RenderStallThread.h" #include "../Common/GraphicsServerState.h" #include "../Common/SharedGlobal.h" +#include "RequestsInFlightDatabase.h" ///////////////////////////////////////////////////////////////////////////////////////////////////////// /// Checks to see if the app has stopped rendering (or ever rendered at all). @@ -17,12 +18,11 @@ void RenderStallThread::CheckForRenderStall() { static double lastPresentTime = 0.0f; + int delay = 0; + int outerDelay = 0; for (;;) // loop forever { - //int stallCount = 0; - int delay = 0; - if (GetServerShutdownState() == true) { return; @@ -59,14 +59,34 @@ void RenderStallThread::CheckForRenderStall() if (delay > GRAPHICS_SERVER_STATUS_STALL_THRESHOLD_TIME) { SetServerStalledState(true); + +#ifdef CODEXL_GRAPHICS +#ifdef USE_GRAPHICS_SERVER_STATUS_RETURN_CODES + int inFlight = RequestsInFlightDatabase::Instance()->InFlightCount(); + + Log(logMESSAGE, "RenderStallThread::CheckForRenderStall(): App has not rendered for %ld (ms), inFlightCount = %d\n", outerDelay, inFlight); + + if (inFlight > 0) + { + // Send process not running status back to the messages in flight + Log(logMESSAGE, "RenderStallThread::CheckForRenderStall(): Check messages in flight to see if process is still running\n"); + RequestsInFlightDatabase::Instance()->CheckProcessesAreRunning(); + } +#endif +#endif + + delay = 0; } delay += GRAPHICS_SERVER_STATUS_STALL_LOOP_SLEEP_TIME; + + outerDelay += GRAPHICS_SERVER_STATUS_STALL_LOOP_SLEEP_TIME; } else { SetServerStalledState(false); delay = 0; + outerDelay = 0; } } diff --git a/CodeXL/Components/Graphics/Server/WebServer/RequestInFlight.h b/CodeXL/Components/Graphics/Server/WebServer/RequestInFlight.h index 4fffa0306..3bd067975 100755 --- a/CodeXL/Components/Graphics/Server/WebServer/RequestInFlight.h +++ b/CodeXL/Components/Graphics/Server/WebServer/RequestInFlight.h @@ -19,17 +19,20 @@ class RequestInFlight /// Constructor /// \param pRequestHeader Input request /// \param pClientSocket Client socket - RequestInFlight(HTTPRequestHeader* pRequestHeader, NetSocket* pClientSocket) + /// \param processID The process ID + RequestInFlight(HTTPRequestHeader* pRequestHeader, NetSocket* pClientSocket, unsigned long processID) { m_pRequestHeader = pRequestHeader; m_pClientSocket = pClientSocket; + m_processID = processID; } -private: - HTTPRequestHeader* m_pRequestHeader; ///< Stores the request in flight + HTTPRequestHeader* m_pRequestHeader; ///< Stores the request header - NetSocket* m_pClientSocket; ///< STores teh client socket + NetSocket* m_pClientSocket; ///< Stores the client socket + + unsigned long m_processID; ///< Record the process ID }; diff --git a/CodeXL/Components/Graphics/Server/WebServer/RequestsInFlightDatabase.h b/CodeXL/Components/Graphics/Server/WebServer/RequestsInFlightDatabase.h index 1e198bda0..41194a4bb 100755 --- a/CodeXL/Components/Graphics/Server/WebServer/RequestsInFlightDatabase.h +++ b/CodeXL/Components/Graphics/Server/WebServer/RequestsInFlightDatabase.h @@ -8,12 +8,14 @@ #include "RequestInFlight.h" #include "../Common/NetSocket.h" +#include "ProcessTracker.h" #ifndef REQUESTS_IN_FLIGHT_DATABASE_H_ #define REQUESTS_IN_FLIGHT_DATABASE_H_ /// Record the requests that are sent to the server typedef std::map RequestsInFlightDB; +typedef std::map::iterator RequestsInFlightDBIter; /// Responsible for tracking commands that are currently in the shared memory /// being processed by the graphics server @@ -44,6 +46,9 @@ class RequestsInFlightDatabase : public TSingleton< RequestsInFlightDatabase > { ScopeLock sc(m_mutex); m_RequestsInFlight[pSocket] = pRequest; + + // Used for debugging + Log(logMESSAGE, "Adding request socket 0x%p\n", pSocket); } /// Remove a tracked request from this DB @@ -52,6 +57,64 @@ class RequestsInFlightDatabase : public TSingleton< RequestsInFlightDatabase > { ScopeLock sc(m_mutex); m_RequestsInFlight.erase(pSocket); + + // Used for debugging + Log(logMESSAGE, "Removing request socket 0x%p\n", pSocket); + } + + /// Get a count of the number of requests in flight + /// \return Number of requests in flight + int InFlightCount() + { + return (int)m_RequestsInFlight.size(); + } + + /// Sends the stalled state to all commands in flight + void SendServerStalledStateToAll() + { + ScopeLock sc(m_mutex); + RequestsInFlightDBIter iter = m_RequestsInFlight.begin(); + while (iter != m_RequestsInFlight.end()) + { + RequestInFlight* pRequest = iter->second; + + ProcessTracker::Instance()->HandleServerStatusResponse(GRAPHICS_SERVER_STATE_PROCESS_NOT_RUNNING, pRequest->m_pRequestHeader, pRequest->m_pClientSocket); + + ++iter; + } + } + + /// Checks to see if the process that a request was sent to is still running. + void CheckProcessesAreRunning() + { + ScopeLock sc(m_mutex); + RequestsInFlightDBIter iter = m_RequestsInFlight.begin(); + while (iter != m_RequestsInFlight.end()) + { + NetSocket* pSock = iter->first; + RequestInFlight* pRequest = iter->second; + + unsigned long pid = pRequest->m_processID; + bool isAlive = true; + osIsProcessAlive((DWORD)pid, isAlive); + + Log(logMESSAGE, "CheckProcessesAreRunning:: Checking for process %ld\n", pid); + + if (isAlive == false) + { + Log(logMESSAGE, "CheckProcessesAreRunning::Process %ld is not running: URL = %s\n", pid, pRequest->m_pRequestHeader->GetUrl()); + // Need to return the correct error data for process not running + ProcessTracker::Instance()->HandleServerStatusResponse(GRAPHICS_SERVER_STATE_PROCESS_NOT_RUNNING, pRequest->m_pRequestHeader, pRequest->m_pClientSocket); + // Clear the request + m_RequestsInFlight.erase(pSock); + } + else + { + Log(logMESSAGE, "CheckProcessesAreRunning:: Process %ld is running\n", pid); + } + + ++iter; + } } private: