486 m_ServerRunning = TRUE; |
486 m_ServerRunning = TRUE; |
487 |
487 |
488 TCDEBUGLOGA1("CClientManager::StartServer end numRefs = %d\n", pData->numRefs); |
488 TCDEBUGLOGA1("CClientManager::StartServer end numRefs = %d\n", pData->numRefs); |
489 return ret; |
489 return ret; |
490 } |
490 } |
491 |
491 BOOL CClientManager::IsTCFServerActive(DWORD processId) |
|
492 { |
|
493 HANDLE h = ::OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, processId); |
|
494 if (h) |
|
495 { |
|
496 // is it really still alive? |
|
497 DWORD exitCode = -5; |
|
498 BOOL exitCall = ::GetExitCodeProcess(h, &exitCode); |
|
499 ::CloseHandle(h); |
|
500 if (exitCall == TRUE && exitCode != STILL_ACTIVE) |
|
501 { |
|
502 // TCFServer is really dead |
|
503 return FALSE; |
|
504 } |
|
505 else |
|
506 { |
|
507 // TCFServer is still active |
|
508 return TRUE; |
|
509 } |
|
510 } |
|
511 else |
|
512 { |
|
513 // TCFServer is really dead |
|
514 return FALSE; |
|
515 } |
|
516 } |
492 long CClientManager::StopServer() |
517 long CClientManager::StopServer() |
493 { |
518 { |
494 long ret = TCAPI_ERR_NONE; |
519 long ret = TCAPI_ERR_NONE; |
495 pServerProcessData pData = m_Server->GetProcessPtr(); |
520 pServerProcessData pData = m_Server->GetProcessPtr(); |
496 |
521 |
514 else |
539 else |
515 { |
540 { |
516 // substract ref count |
541 // substract ref count |
517 pData->numRefs--; |
542 pData->numRefs--; |
518 if (pData->numRefs < 0) pData->numRefs = 0; |
543 if (pData->numRefs < 0) pData->numRefs = 0; |
|
544 |
|
545 bool sendStop = true; |
|
546 if (!IsTCFServerActive(pData->serverProcess.dwProcessId)) |
|
547 { |
|
548 sendStop = false; |
|
549 pData->numRefs = 0; |
|
550 } |
|
551 |
519 // if refcount == 0 then really stop the server process |
552 // if refcount == 0 then really stop the server process |
520 if (pData->numRefs == 0) |
553 if (pData->numRefs == 0) |
521 { |
554 { |
522 // last client process is closing |
555 if (sendStop) |
523 // tell server to exit |
556 { |
524 ServerCommandData cmdrsp; |
557 // last client process is closing |
525 cmdrsp.command = eCmdExit; |
558 // tell server to exit |
526 |
559 ServerCommandData cmdrsp; |
527 TCDEBUGLOGS(" SendCommand eCmdExit\n"); |
560 cmdrsp.command = eCmdExit; |
528 m_Server->SendCommand(&cmdrsp); |
561 |
529 TCDEBUGLOGS(" GetResponse eExit\n"); |
562 TCDEBUGLOGS(" SendCommand eCmdExit\n"); |
530 m_Server->GetResponse(&cmdrsp); |
563 m_Server->SendCommand(&cmdrsp); |
531 |
564 TCDEBUGLOGS(" GetResponse eExit\n"); |
532 // wait for process to exit |
565 m_Server->GetResponse(&cmdrsp); |
533 TCDEBUGLOGS(" WaitForSingleObject start\n"); |
566 |
534 DWORD waitErr = ::WaitForSingleObject(m_hServer, 10000L /*INFINITE*/); |
567 // wait for process to exit |
535 TCDEBUGLOGA1("CClientManager::StopServer WaitForSingleObject = %d\n", waitErr); |
568 TCDEBUGLOGS(" WaitForSingleObject start\n"); |
|
569 DWORD waitErr = ::WaitForSingleObject(m_hServer, 10000L /*INFINITE*/); |
|
570 TCDEBUGLOGA1("CClientManager::StopServer WaitForSingleObject = %d\n", waitErr); |
|
571 } |
536 |
572 |
537 // now close our handle to server process |
573 // now close our handle to server process |
538 if (m_hServer != NULL) |
574 if (m_hServer != NULL) |
539 { |
575 { |
540 CloseHandle(m_hServer); |
576 CloseHandle(m_hServer); |
578 } |
614 } |
579 |
615 |
580 BOOL CClientManager::IsServerRunning() |
616 BOOL CClientManager::IsServerRunning() |
581 { |
617 { |
582 pServerProcessData pData = m_Server->GetProcessPtr(); |
618 pServerProcessData pData = m_Server->GetProcessPtr(); |
583 if (pData->serverProcess.hProcess != NULL) |
619 if (IsTCFServerActive(pData->serverProcess.dwProcessId)) |
|
620 { |
584 return TRUE; |
621 return TRUE; |
|
622 } |
585 else |
623 else |
|
624 { |
586 return FALSE; |
625 return FALSE; |
587 |
626 } |
588 } |
627 } |
589 |
628 |
590 void CClientManager::CreateLockFile(DWORD processId) |
629 void CClientManager::CreateLockFile(DWORD processId) |
591 { |
630 { |
592 if (m_ServerLockFile != NULL) |
631 if (m_ServerLockFile != NULL) |
661 if (f) |
700 if (f) |
662 { |
701 { |
663 BOOL done = FALSE; |
702 BOOL done = FALSE; |
664 while (!done) |
703 while (!done) |
665 { |
704 { |
666 DWORD cId = 0xffffffff; |
705 DWORD creatorId = 0xffffffff; |
667 DWORD sId = 0xffffffff; |
706 DWORD serverId = 0xffffffff; |
668 int n = fscanf(f, "%ld %ld\n", &cId, &sId); |
707 int n = fscanf(f, "%ld %ld\n", &creatorId, &serverId); |
669 if (n == 2) |
708 if (n == 2) |
670 { |
709 { |
671 TCDEBUGLOGA3("CClientManager::DeleteFromLockFile numIds=%d sId=%d pId=%d\n", numIds, cId, sId); |
710 TCDEBUGLOGA3("CClientManager::DeleteFromLockFile numIds=%d creatorId=%d serverId=%d\n", numIds, creatorId, serverId); |
672 if (cId != ourProcessId || sId != serverProcessId) |
711 if (creatorId != ourProcessId || serverId != serverProcessId) |
673 { |
712 { |
674 callingId[numIds] = cId; |
713 creatorIds[numIds] = creatorId; |
675 serverId[numIds] = sId; |
714 serverIds[numIds] = serverId; |
676 numIds++; |
715 numIds++; |
677 if (numIds > 9) |
716 if (numIds > 9) |
678 done = TRUE; |
717 done = TRUE; |
679 } |
718 } |
680 } |
719 } |
706 |
745 |
707 // Currently assumes there is only ONE TCFServer, but multiple client processes (that use that server) |
746 // Currently assumes there is only ONE TCFServer, but multiple client processes (that use that server) |
708 // we should not have more than a few Carbide processes connecting to the same TCFServer |
747 // we should not have more than a few Carbide processes connecting to the same TCFServer |
709 void CClientManager::TerminateServerThroughLockFile(pServerProcessData pData) |
748 void CClientManager::TerminateServerThroughLockFile(pServerProcessData pData) |
710 { |
749 { |
711 DWORD callingId[10]; |
750 DWORD creatorIds[10]; |
712 DWORD serverId[10]; |
751 DWORD serverIds[10]; |
713 BOOL liveCaller[10]; |
752 BOOL liveCaller[10]; |
714 int numIds = 0; |
753 int numIds = 0; |
715 if (m_ServerLockFile != NULL) |
754 if (m_ServerLockFile != NULL) |
716 { |
755 { |
717 DWORD attr = ::GetFileAttributes(m_ServerLockFile); |
756 DWORD attr = ::GetFileAttributes(m_ServerLockFile); |
727 if (f) |
766 if (f) |
728 { |
767 { |
729 BOOL done = FALSE; |
768 BOOL done = FALSE; |
730 while (!done) |
769 while (!done) |
731 { |
770 { |
732 DWORD cId = 0xffffffff; |
771 DWORD creatorId = 0xffffffff; |
733 DWORD sId = 0xffffffff; |
772 DWORD serverId = 0xffffffff; |
734 int n = fscanf(f, "%ld %ld\n", &cId, &sId); |
773 int n = fscanf(f, "%ld %ld\n", &creatorId, &serverId); |
735 if (n == 2) |
774 if (n == 2) |
736 { |
775 { |
737 TCDEBUGLOGA3("CClientManager::TerminateServerThroughLockFile n=%d sId=%d pId=%d\n", n, cId, sId); |
776 TCDEBUGLOGA3("CClientManager::TerminateServerThroughLockFile n=%d creatorId=%d serverId=%d\n", n, creatorId, serverId); |
738 callingId[numIds] = cId; |
777 creatorIds[numIds] = creatorId; |
739 serverId[numIds] = sId; |
778 serverIds[numIds] = serverId; |
740 numIds++; |
779 numIds++; |
741 if (numIds > 9) |
780 if (numIds > 9) |
742 done = TRUE; |
781 done = TRUE; |
743 } |
782 } |
744 else |
783 else |
749 fclose(f); |
788 fclose(f); |
750 |
789 |
751 int numDeadCallers = 0; |
790 int numDeadCallers = 0; |
752 for (int i = 0; i < numIds; i++) |
791 for (int i = 0; i < numIds; i++) |
753 { |
792 { |
754 HANDLE h = ::OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, callingId[i]); |
793 HANDLE h = ::OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, creatorIds[i]); |
755 if (h) |
794 if (h) |
756 { |
795 { |
757 // calling process is still alive |
796 // calling process is still alive |
758 liveCaller[i] = TRUE; |
797 liveCaller[i] = TRUE; |
|
798 DWORD exitCode = -5; |
|
799 BOOL exitCall = ::GetExitCodeProcess(h, &exitCode); |
|
800 DWORD id = ::GetCurrentProcessId(); |
759 ::CloseHandle(h); |
801 ::CloseHandle(h); |
760 TCDEBUGLOGA1("CClientManager::TerminateServerThroughLockFile %d alive\n", callingId[i]); |
802 TCDEBUGLOGA3("CClientManager::TerminateServerThroughLockFile %d alive exitCall=%d currentId=%d\n", creatorIds[i], exitCall, id); |
|
803 if (exitCall == TRUE && exitCode != STILL_ACTIVE) |
|
804 { |
|
805 liveCaller[i] = FALSE; |
|
806 numDeadCallers++; |
|
807 } |
|
808 { |
|
809 TCDEBUGLOGA2("CClientManager::TerminateServerThroughLockFile exitCode=%d still_active=%d\n", exitCode, STILL_ACTIVE); |
|
810 } |
761 } |
811 } |
762 else |
812 else |
763 { |
813 { |
764 liveCaller[i] = FALSE; |
814 liveCaller[i] = FALSE; |
765 numDeadCallers++; |
815 numDeadCallers++; |
766 DWORD err = ::GetLastError(); |
816 DWORD err = ::GetLastError(); |
767 TCDEBUGLOGA3("CClientManager::TerminateServerThroughLockFile %d dead err=%d:%s\n", callingId[i], err, GetErrorText(err)); |
817 TCDEBUGLOGA3("CClientManager::TerminateServerThroughLockFile %d dead err=%d:%s\n", creatorIds[i], err, GetErrorText(err)); |
768 } |
818 } |
769 } |
819 } |
770 if (numDeadCallers == numIds) |
820 if (numDeadCallers == numIds) |
771 { |
821 { |
|
822 // All clients of this TCFServer are dead |
772 // terminate the TCFServer, and delete lock file |
823 // terminate the TCFServer, and delete lock file |
773 pData->numRefs = 0; |
824 pData->numRefs = 0; |
774 ::remove(m_ServerLockFile); |
825 ::remove(m_ServerLockFile); |
775 HANDLE h = ::OpenProcess(SYNCHRONIZE|PROCESS_TERMINATE, FALSE, serverId[0]); |
826 HANDLE h = ::OpenProcess(SYNCHRONIZE|PROCESS_TERMINATE, FALSE, serverIds[0]); |
776 if (h) |
827 if (h) |
777 { |
828 { |
778 BOOL ret = ::TerminateProcess(h, -1); |
829 BOOL ret = ::TerminateProcess(h, -1); |
779 if (ret == 0) |
830 if (ret == 0) |
780 { |
831 { |
784 ::CloseHandle(h); |
835 ::CloseHandle(h); |
785 } |
836 } |
786 } |
837 } |
787 else |
838 else |
788 { |
839 { |
789 // leave TCFServer running, recreate lock file and save live callers |
840 // some java clients are still alive |
790 ::remove(m_ServerLockFile); |
841 // check to see if TCFServer is still alive |
791 f = fopen(m_ServerLockFile, "wt"); |
842 if (IsTCFServerActive(serverIds[0])) |
792 if (f) |
|
793 { |
843 { |
794 for (int i = 0; i < numIds; i++) |
844 // TCFServer is still active |
|
845 // leave TCFServer running, recreate lock file and save live callers |
|
846 ::remove(m_ServerLockFile); |
|
847 f = fopen(m_ServerLockFile, "wt"); |
|
848 if (f) |
795 { |
849 { |
796 if (liveCaller[i]) |
850 for (int i = 0; i < numIds; i++) |
797 { |
851 { |
798 fprintf(f, "%ld %ld\n", callingId[i], serverId[i]); |
852 if (liveCaller[i]) |
|
853 { |
|
854 fprintf(f, "%ld %ld\n", creatorIds[i], serverIds[i]); |
|
855 } |
799 } |
856 } |
|
857 fclose(f); |
800 } |
858 } |
801 fclose(f); |
859 pData->numRefs -= numDeadCallers; |
|
860 if (pData->numRefs < 0) pData->numRefs = 0; |
802 } |
861 } |
803 pData->numRefs -= numDeadCallers; |
862 else |
804 if (pData->numRefs < 0) pData->numRefs = 0; |
863 { |
|
864 // TCFServer is really dead |
|
865 pData->numRefs = 0; |
|
866 ::remove(m_ServerLockFile); |
|
867 } |
805 } |
868 } |
806 } |
869 } |
807 else |
870 else |
808 { |
871 { |
809 // error opening lock file |
872 // error opening lock file |
|
873 // perhaps the user deleted it, |
|
874 // if so, we assume he has also deleted the TCFServer as we now have no way of verifying if the |
|
875 // process is dead. |
|
876 pData->numRefs = 0; |
810 DWORD err = ::GetLastError(); |
877 DWORD err = ::GetLastError(); |
811 TCDEBUGLOGA2("CClientManager::TerminateServerThroughLockFile fopenErr=%d:%s\n", err, GetErrorText(err)); |
878 TCDEBUGLOGA2("CClientManager::TerminateServerThroughLockFile fopenErr=%d:%s\n", err, GetErrorText(err)); |
812 } |
879 } |
813 } |
880 } |
814 } |
881 } |