--- a/connectivity/com.nokia.tcf/native/TCFNative/TCFClient/ClientManager.cpp Wed Feb 10 13:45:43 2010 -0600
+++ b/connectivity/com.nokia.tcf/native/TCFNative/TCFClient/ClientManager.cpp Wed Feb 10 14:32:22 2010 -0600
@@ -488,7 +488,32 @@
TCDEBUGLOGA1("CClientManager::StartServer end numRefs = %d\n", pData->numRefs);
return ret;
}
-
+BOOL CClientManager::IsTCFServerActive(DWORD processId)
+{
+ HANDLE h = ::OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, processId);
+ if (h)
+ {
+ // is it really still alive?
+ DWORD exitCode = -5;
+ BOOL exitCall = ::GetExitCodeProcess(h, &exitCode);
+ ::CloseHandle(h);
+ if (exitCall == TRUE && exitCode != STILL_ACTIVE)
+ {
+ // TCFServer is really dead
+ return FALSE;
+ }
+ else
+ {
+ // TCFServer is still active
+ return TRUE;
+ }
+ }
+ else
+ {
+ // TCFServer is really dead
+ return FALSE;
+ }
+}
long CClientManager::StopServer()
{
long ret = TCAPI_ERR_NONE;
@@ -516,23 +541,34 @@
// substract ref count
pData->numRefs--;
if (pData->numRefs < 0) pData->numRefs = 0;
+
+ bool sendStop = true;
+ if (!IsTCFServerActive(pData->serverProcess.dwProcessId))
+ {
+ sendStop = false;
+ pData->numRefs = 0;
+ }
+
// if refcount == 0 then really stop the server process
if (pData->numRefs == 0)
{
- // last client process is closing
- // tell server to exit
- ServerCommandData cmdrsp;
- cmdrsp.command = eCmdExit;
-
- TCDEBUGLOGS(" SendCommand eCmdExit\n");
- m_Server->SendCommand(&cmdrsp);
- TCDEBUGLOGS(" GetResponse eExit\n");
- m_Server->GetResponse(&cmdrsp);
-
- // wait for process to exit
- TCDEBUGLOGS(" WaitForSingleObject start\n");
- DWORD waitErr = ::WaitForSingleObject(m_hServer, 10000L /*INFINITE*/);
- TCDEBUGLOGA1("CClientManager::StopServer WaitForSingleObject = %d\n", waitErr);
+ if (sendStop)
+ {
+ // last client process is closing
+ // tell server to exit
+ ServerCommandData cmdrsp;
+ cmdrsp.command = eCmdExit;
+
+ TCDEBUGLOGS(" SendCommand eCmdExit\n");
+ m_Server->SendCommand(&cmdrsp);
+ TCDEBUGLOGS(" GetResponse eExit\n");
+ m_Server->GetResponse(&cmdrsp);
+
+ // wait for process to exit
+ TCDEBUGLOGS(" WaitForSingleObject start\n");
+ DWORD waitErr = ::WaitForSingleObject(m_hServer, 10000L /*INFINITE*/);
+ TCDEBUGLOGA1("CClientManager::StopServer WaitForSingleObject = %d\n", waitErr);
+ }
// now close our handle to server process
if (m_hServer != NULL)
@@ -580,11 +616,14 @@
BOOL CClientManager::IsServerRunning()
{
pServerProcessData pData = m_Server->GetProcessPtr();
- if (pData->serverProcess.hProcess != NULL)
+ if (IsTCFServerActive(pData->serverProcess.dwProcessId))
+ {
return TRUE;
+ }
else
+ {
return FALSE;
-
+ }
}
void CClientManager::CreateLockFile(DWORD processId)
@@ -640,8 +679,8 @@
void CClientManager::DeleteFromLockFile(DWORD serverProcessId)
{
- DWORD callingId[10];
- DWORD serverId[10];
+ DWORD creatorIds[10];
+ DWORD serverIds[10];
int numIds = 0;
DWORD ourProcessId = ::GetCurrentProcessId();
@@ -663,16 +702,16 @@
BOOL done = FALSE;
while (!done)
{
- DWORD cId = 0xffffffff;
- DWORD sId = 0xffffffff;
- int n = fscanf(f, "%ld %ld\n", &cId, &sId);
+ DWORD creatorId = 0xffffffff;
+ DWORD serverId = 0xffffffff;
+ int n = fscanf(f, "%ld %ld\n", &creatorId, &serverId);
if (n == 2)
{
- TCDEBUGLOGA3("CClientManager::DeleteFromLockFile numIds=%d sId=%d pId=%d\n", numIds, cId, sId);
- if (cId != ourProcessId || sId != serverProcessId)
+ TCDEBUGLOGA3("CClientManager::DeleteFromLockFile numIds=%d creatorId=%d serverId=%d\n", numIds, creatorId, serverId);
+ if (creatorId != ourProcessId || serverId != serverProcessId)
{
- callingId[numIds] = cId;
- serverId[numIds] = sId;
+ creatorIds[numIds] = creatorId;
+ serverIds[numIds] = serverId;
numIds++;
if (numIds > 9)
done = TRUE;
@@ -695,7 +734,7 @@
{
for (int i = 0; i < numIds; i++)
{
- fprintf(f, "%ld %ld\n", callingId[i], serverId[i]);
+ fprintf(f, "%ld %ld\n", creatorIds[i], serverIds[i]);
}
fclose(f);
}
@@ -708,8 +747,8 @@
// we should not have more than a few Carbide processes connecting to the same TCFServer
void CClientManager::TerminateServerThroughLockFile(pServerProcessData pData)
{
- DWORD callingId[10];
- DWORD serverId[10];
+ DWORD creatorIds[10];
+ DWORD serverIds[10];
BOOL liveCaller[10];
int numIds = 0;
if (m_ServerLockFile != NULL)
@@ -729,14 +768,14 @@
BOOL done = FALSE;
while (!done)
{
- DWORD cId = 0xffffffff;
- DWORD sId = 0xffffffff;
- int n = fscanf(f, "%ld %ld\n", &cId, &sId);
+ DWORD creatorId = 0xffffffff;
+ DWORD serverId = 0xffffffff;
+ int n = fscanf(f, "%ld %ld\n", &creatorId, &serverId);
if (n == 2)
{
- TCDEBUGLOGA3("CClientManager::TerminateServerThroughLockFile n=%d sId=%d pId=%d\n", n, cId, sId);
- callingId[numIds] = cId;
- serverId[numIds] = sId;
+ TCDEBUGLOGA3("CClientManager::TerminateServerThroughLockFile n=%d creatorId=%d serverId=%d\n", n, creatorId, serverId);
+ creatorIds[numIds] = creatorId;
+ serverIds[numIds] = serverId;
numIds++;
if (numIds > 9)
done = TRUE;
@@ -751,28 +790,40 @@
int numDeadCallers = 0;
for (int i = 0; i < numIds; i++)
{
- HANDLE h = ::OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, callingId[i]);
+ HANDLE h = ::OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, creatorIds[i]);
if (h)
{
// calling process is still alive
liveCaller[i] = TRUE;
+ DWORD exitCode = -5;
+ BOOL exitCall = ::GetExitCodeProcess(h, &exitCode);
+ DWORD id = ::GetCurrentProcessId();
::CloseHandle(h);
- TCDEBUGLOGA1("CClientManager::TerminateServerThroughLockFile %d alive\n", callingId[i]);
+ TCDEBUGLOGA3("CClientManager::TerminateServerThroughLockFile %d alive exitCall=%d currentId=%d\n", creatorIds[i], exitCall, id);
+ if (exitCall == TRUE && exitCode != STILL_ACTIVE)
+ {
+ liveCaller[i] = FALSE;
+ numDeadCallers++;
+ }
+ {
+ TCDEBUGLOGA2("CClientManager::TerminateServerThroughLockFile exitCode=%d still_active=%d\n", exitCode, STILL_ACTIVE);
+ }
}
else
{
liveCaller[i] = FALSE;
numDeadCallers++;
DWORD err = ::GetLastError();
- TCDEBUGLOGA3("CClientManager::TerminateServerThroughLockFile %d dead err=%d:%s\n", callingId[i], err, GetErrorText(err));
+ TCDEBUGLOGA3("CClientManager::TerminateServerThroughLockFile %d dead err=%d:%s\n", creatorIds[i], err, GetErrorText(err));
}
}
if (numDeadCallers == numIds)
{
+ // All clients of this TCFServer are dead
// terminate the TCFServer, and delete lock file
pData->numRefs = 0;
::remove(m_ServerLockFile);
- HANDLE h = ::OpenProcess(SYNCHRONIZE|PROCESS_TERMINATE, FALSE, serverId[0]);
+ HANDLE h = ::OpenProcess(SYNCHRONIZE|PROCESS_TERMINATE, FALSE, serverIds[0]);
if (h)
{
BOOL ret = ::TerminateProcess(h, -1);
@@ -786,27 +837,43 @@
}
else
{
- // leave TCFServer running, recreate lock file and save live callers
- ::remove(m_ServerLockFile);
- f = fopen(m_ServerLockFile, "wt");
- if (f)
+ // some java clients are still alive
+ // check to see if TCFServer is still alive
+ if (IsTCFServerActive(serverIds[0]))
{
- for (int i = 0; i < numIds; i++)
+ // TCFServer is still active
+ // leave TCFServer running, recreate lock file and save live callers
+ ::remove(m_ServerLockFile);
+ f = fopen(m_ServerLockFile, "wt");
+ if (f)
{
- if (liveCaller[i])
+ for (int i = 0; i < numIds; i++)
{
- fprintf(f, "%ld %ld\n", callingId[i], serverId[i]);
+ if (liveCaller[i])
+ {
+ fprintf(f, "%ld %ld\n", creatorIds[i], serverIds[i]);
+ }
}
+ fclose(f);
}
- fclose(f);
+ pData->numRefs -= numDeadCallers;
+ if (pData->numRefs < 0) pData->numRefs = 0;
}
- pData->numRefs -= numDeadCallers;
- if (pData->numRefs < 0) pData->numRefs = 0;
+ else
+ {
+ // TCFServer is really dead
+ pData->numRefs = 0;
+ ::remove(m_ServerLockFile);
+ }
}
}
else
{
// error opening lock file
+ // perhaps the user deleted it,
+ // if so, we assume he has also deleted the TCFServer as we now have no way of verifying if the
+ // process is dead.
+ pData->numRefs = 0;
DWORD err = ::GetLastError();
TCDEBUGLOGA2("CClientManager::TerminateServerThroughLockFile fopenErr=%d:%s\n", err, GetErrorText(err));
}
--- a/connectivity/com.nokia.tcf/src/com/nokia/tcf/impl/TCAPIConnection.java Wed Feb 10 13:45:43 2010 -0600
+++ b/connectivity/com.nokia.tcf/src/com/nokia/tcf/impl/TCAPIConnection.java Wed Feb 10 14:32:22 2010 -0600
@@ -46,7 +46,12 @@
} catch (UnsatisfiedLinkError e) {
// if Carbide DLL is not found in DE,
// try to load one from the plugin itself
- System.loadLibrary("TCFClient");
+ try {
+ System.loadLibrary("TCFClient");
+ } catch (UnsatisfiedLinkError e2) {
+ // no native TCF, e.g., not on Windows or in a misconfigured dev layout
+ e2.printStackTrace();
+ }
}
}
}
@@ -354,6 +359,23 @@
this.cookie.setConnected(true);
this.connection = inConnection;
this.messageOptions = inMessageOptions;
+ } else if (ret == TCErrorConstants.TCAPI_ERR_COMM_SERVER_RESPONSE_TIMEOUT){
+ // TCFServer may have died, attempt to restart it
+ ret = nativeStartServer();
+ if (ret == TCErrorConstants.TCAPI_ERR_NONE) {
+ // now try connecting again
+ ret = nativeConnect(type, options, settings, moptions, filePath, clientId);
+ if (ret == TCErrorConstants.TCAPI_ERR_NONE) {
+ this.cookie.setClientId(clientId[0]);
+ this.cookie.setConnected(true);
+ this.connection = inConnection;
+ this.messageOptions = inMessageOptions;
+ } else {
+ status = new Status(Status.ERROR, Activator.PLUGIN_ID, (int)ret, TCErrorConstants.getErrorMessage(ret), null);
+ }
+ } else {
+ status = new Status(Status.ERROR, Activator.PLUGIN_ID, (int)ret, TCErrorConstants.getErrorMessage(ret), null);
+ }
} else {
status = new Status(Status.ERROR, Activator.PLUGIN_ID, (int)ret, TCErrorConstants.getErrorMessage(ret), null);
}