diff --git a/checkin_notes b/checkin_notes index fa44b9bb23..2cae3d3a8c 100644 --- a/checkin_notes +++ b/checkin_notes @@ -930,3 +930,23 @@ Charlie Jan 29 2008 lib/ gui_rpc_client.h gui_rpc_client_ops.C + +Rom Jan 30 2008 + - MGR: Change the CC startup logic so that more informative error + messages. + + Policy Change: When installed as a service or daemon, the service + or daemon manager should start BOINC, not the BOINC Manager. + (Windows Only for right now, should eventually be applied + to all platforms) + - LIB: Undue my previous change that launched graphics apps as + an idle process. + - LIB: Take care of some warnings. + + clientgui/ + BOINCBaseFrame.cpp, .h + BOINCClientManager.cpp, .h (Added) + BOINCGUIApp.cpp, .h + MainDocument.cpp, .h + lib/ + util.C diff --git a/clientgui/BOINCBaseFrame.cpp b/clientgui/BOINCBaseFrame.cpp index 6273b4d8ce..4c5dfcb6bb 100644 --- a/clientgui/BOINCBaseFrame.cpp +++ b/clientgui/BOINCBaseFrame.cpp @@ -32,6 +32,7 @@ #include "BOINCGUIApp.h" #include "SkinManager.h" #include "MainDocument.h" +#include "BOINCClientManager.h" #include "BOINCTaskBar.h" #include "BOINCBaseFrame.h" #include "BOINCDialupManager.h" @@ -177,16 +178,6 @@ void CBOINCBaseFrame::OnAlertPoll(wxTimerEvent& WXUNUSED(event)) { void CBOINCBaseFrame::OnInitialized(CFrameEvent& WXUNUSED(event)) { wxLogTrace(wxT("Function Start/End"), wxT("CBOINCBaseFrame::OnInitialized - Function Begin")); - - CMainDocument* pDoc = wxGetApp().GetDocument(); - - wxASSERT(pDoc); - wxASSERT(wxDynamicCast(pDoc, CMainDocument)); - - if (!pDoc->IsConnected()) { - pDoc->Connect(wxT("localhost"), wxEmptyString, TRUE, TRUE); - } - wxLogTrace(wxT("Function Start/End"), wxT("CBOINCBaseFrame::OnInitialized - Function End")); } @@ -407,7 +398,7 @@ void CBOINCBaseFrame::ShowConnectionFailedAlert() { // Did BOINC crash? If so restart it. - wxGetApp().AutoRestartBOINC(); + wxGetApp().GetDocument()->m_pClientManager->AutoRestart(); // %s is the application name @@ -440,6 +431,57 @@ void CBOINCBaseFrame::ShowConnectionFailedAlert() { } +void CBOINCBaseFrame::ShowDaemonStartFailedAlert() { + CSkinAdvanced* pSkinAdvanced = wxGetApp().GetSkinManager()->GetAdvanced(); + wxString strDialogTitle = wxEmptyString; + wxString strDialogMessage = wxEmptyString; + + + wxASSERT(pSkinAdvanced); + wxASSERT(wxDynamicCast(pSkinAdvanced, CSkinAdvanced)); + + + wxLogTrace(wxT("Function Start/End"), wxT("CBOINCBaseFrame::ShowDaemonStartFailedAlert - Function Begin")); + + + // %s is the application name + // i.e. 'BOINC Manager', 'GridRepublic Manager' + strDialogTitle.Printf( + _("%s - Daemon Start Failed"), + pSkinAdvanced->GetApplicationName().c_str() + ); + + // 1st %s is the application name + // i.e. 'BOINC Manager', 'GridRepublic Manager' + // 2st %s is the project name + // i.e. 'BOINC', 'GridRepublic' +#ifdef __WXMSW__ + strDialogMessage.Printf( + _("%s is not able to start a %s client.\n" + "Please launch the Control Panel->Administative Tools->Services " + "applet and start the BOINC service."), + pSkinAdvanced->GetApplicationName().c_str(), + pSkinAdvanced->GetApplicationShortName().c_str() + ); +#else + strDialogMessage.Printf( + _("%s is not able to start a %s client.\n" + "Please start the daemon and try again."), + pSkinAdvanced->GetApplicationName().c_str(), + pSkinAdvanced->GetApplicationShortName().c_str() + ); +#endif + + ShowAlert( + strDialogTitle, + strDialogMessage, + wxOK | wxICON_ERROR + ); + + wxLogTrace(wxT("Function Start/End"), wxT("CBOINCBaseFrame::ShowDaemonStartFailedAlert - Function End")); +} + + void CBOINCBaseFrame::ShowNotCurrentlyConnectedAlert() { CSkinAdvanced* pSkinAdvanced = wxGetApp().GetSkinManager()->GetAdvanced(); wxString strDialogTitle = wxEmptyString; @@ -454,7 +496,7 @@ void CBOINCBaseFrame::ShowNotCurrentlyConnectedAlert() { // Did BOINC crash? If so restart it. - wxGetApp().AutoRestartBOINC(); + wxGetApp().GetDocument()->m_pClientManager->AutoRestart(); // %s is the application name diff --git a/clientgui/BOINCBaseFrame.h b/clientgui/BOINCBaseFrame.h index 849d93d234..9fc8e6640f 100644 --- a/clientgui/BOINCBaseFrame.h +++ b/clientgui/BOINCBaseFrame.h @@ -71,6 +71,7 @@ public: void FireReloadSkin(); void ShowConnectionBadPasswordAlert( bool bUsedDefaultPassword, int m_iReadGUIRPCAuthFailure ); void ShowConnectionFailedAlert(); + void ShowDaemonStartFailedAlert(); void ShowNotCurrentlyConnectedAlert(); virtual void StartTimers(); diff --git a/clientgui/BOINCClientManager.cpp b/clientgui/BOINCClientManager.cpp new file mode 100644 index 0000000000..61b923c142 --- /dev/null +++ b/clientgui/BOINCClientManager.cpp @@ -0,0 +1,469 @@ +// Berkeley Open Infrastructure for Network Computing +// http://boinc.berkeley.edu +// Copyright (C) 2005 University of California +// +// This is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; +// either version 2.1 of the License, or (at your option) any later version. +// +// This software is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU Lesser General Public License for more details. +// +// To view the GNU Lesser General Public License visit +// http://www.gnu.org/copyleft/lesser.html +// or write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +#if defined(__GNUG__) && !defined(__APPLE__) +#pragma implementation "BOINCClientManager.h" +#endif + +#include "stdwx.h" +#include "diagnostics.h" +#include "LogBOINC.h" +#include "BOINCGUIApp.h" +#include "MainDocument.h" +#include "BOINCBaseFrame.h" +#include "AdvancedFrame.h" +#include "BOINCClientManager.h" + + +#ifdef __WXMSW__ +EXTERN_C BOOL IsBOINCServiceInstalled(); +EXTERN_C BOOL IsBOINCServiceStarting(); +EXTERN_C BOOL IsBOINCServiceRunning(); +EXTERN_C BOOL IsBOINCServiceStopping(); +EXTERN_C BOOL IsBOINCServiceStopped(); +EXTERN_C BOOL StartBOINCService(); +EXTERN_C BOOL StopBOINCService(); +#endif + + +CBOINCClientManager::CBOINCClientManager() { + wxLogTrace(wxT("Function Start/End"), wxT("CBOINCClientManager::CBOINCClientManager - Function Begin")); + + m_bBOINCStartedByManager = false; + m_bClientRunningAsDaemon = false; + m_lBOINCCoreProcessId = 0; + +#ifdef __WXMSW__ + m_hBOINCCoreProcess = NULL; +#endif + + wxLogTrace(wxT("Function Start/End"), wxT("CBOINCClientManager::CBOINCClientManager - Function End")); +} + + +CBOINCClientManager::~CBOINCClientManager() { + wxLogTrace(wxT("Function Start/End"), wxT("CBOINCClientManager::~CBOINCClientManager - Function Begin")); + + wxLogTrace(wxT("Function Start/End"), wxT("CBOINCClientManager::~CBOINCClientManager - Function End")); +} + + +bool CBOINCClientManager::AutoRestart() { + if (!IsBOINCCoreRunning() && m_bBOINCStartedByManager) { + StartupBOINCCore(); + } + return true; +} + + +bool CBOINCClientManager::IsSystemBooting() { + bool bReturnValue = false; +#if defined(__WXMSW__) + if (GetTickCount() < (1000*60*5)) bReturnValue = true; // If system has been up for less than 5 minutes +#elif defined(__WXMAC__) + if (TickCount() < (120*60)) bReturnValue = true; // If system has been up for less than 2 minutes +#endif + return bReturnValue; +} + + +bool CBOINCClientManager::IsBOINCDaemon() { + bool bReturnValue = false; +#if defined(__WXMSW__) + if (IsBOINCServiceInstalled()) bReturnValue = true; +#elif defined(__WXMAC__) + if ( boinc_file_exists("/Library/LaunchDaemons/edu.berkeley.boinc.plist") || // New-style daemon uses launchd + boinc_file_exists("/Library/StartupItems/boinc/boinc") ) { // Old-style daemon uses StartupItem + bReturnValue = true; + } +#endif + return bReturnValue; +} + + +bool CBOINCClientManager::IsBOINCCoreRunning() { + wxLogTrace(wxT("Function Start/End"), wxT("CBOINCClientManager::IsBOINCCoreRunning - Function Begin")); + + int retval; + bool running = false; + HOST_INFO hostinfo; + RPC_CLIENT rpc; + +#ifdef __WXMSW__ + if (IsBOINCServiceInstalled()) { + running = (FALSE != IsBOINCServiceStarting()) || (FALSE != IsBOINCServiceRunning()); + } else { +#endif + // If set up to run as a daemon, allow time for daemon to start up + for (int i=0; i<10; i++) { + retval = rpc.init("localhost"); // synchronous is OK since local + wxLogTrace(wxT("Function Status"), wxT("CBOINCClientManager::IsBOINCCoreRunning - Connecting to core client returned '%d'"), retval); + retval = rpc.get_host_info(hostinfo); + wxLogTrace(wxT("Function Status"), wxT("CBOINCClientManager::IsBOINCCoreRunning - Requesting host info... retval '%d'"), retval); + running = (retval == 0); + rpc.close(); + if (running) break; + if (!IsBOINCDaemon()) break; + wxSleep(1); + } +#ifdef __WXMSW__ + } +#endif + + wxLogTrace(wxT("Function Start/End"), wxT("CBOINCClientManager::IsBOINCCoreRunning - Function End")); + return running; +} + + +bool CBOINCClientManager::StartupBOINCCore() { + bool bReturnValue = false; + +#ifdef __WXMSW__ + if (IsBOINCDaemon()) { + bReturnValue = (StartBOINCService() == TRUE); + } +#endif + if (!IsBOINCCoreRunning() +#ifdef __WXMSW__ + && !IsBOINCDaemon() +#endif + ) { + wxString strExecute = wxEmptyString; + +#if defined(__WXMSW__) + LPTSTR szExecute = NULL; + LPTSTR szDataDirectory = NULL; + + // Append boinc.exe to the end of the strExecute string and get ready to rock + strExecute.Printf( + wxT("\"%s\\boinc.exe\" -redirectio -launched_by_manager %s"), + wxGetApp().GetRootDirectory().c_str(), + wxGetApp().GetArguments().c_str() + ); + + PROCESS_INFORMATION pi; + STARTUPINFO si; + BOOL bProcessStarted; + + memset(&pi, 0, sizeof(pi)); + memset(&si, 0, sizeof(si)); + + si.cb = sizeof(si); + si.dwFlags = STARTF_USESHOWWINDOW; + si.wShowWindow = SW_HIDE; + + szExecute = (LPTSTR)strExecute.c_str(); + if (wxGetApp().GetDataDirectory().empty()) { + szDataDirectory = NULL; + } else { + szDataDirectory = (LPTSTR)wxGetApp().GetDataDirectory().c_str(); + } + + bProcessStarted = CreateProcess( + NULL, + szExecute, + NULL, + NULL, + FALSE, + CREATE_NEW_PROCESS_GROUP|CREATE_NO_WINDOW, + NULL, + szDataDirectory, + &si, + &pi + ); + if (bProcessStarted) { + m_lBOINCCoreProcessId = pi.dwProcessId; + m_hBOINCCoreProcess = pi.hProcess; + } + +#elif defined(__WXMAC__) + + { + wxChar buf[1024]; + wxChar *argv[5]; + ProcessSerialNumber ourPSN; + FSRef ourFSRef; + OSErr err; + + // Get the full path to core client inside this application's bundle + err = GetCurrentProcess (&ourPSN); + if (err == noErr) { + err = GetProcessBundleLocation(&ourPSN, &ourFSRef); + } + if (err == noErr) { + err = FSRefMakePath (&ourFSRef, (UInt8*)buf, sizeof(buf)); + } + if (err == noErr) { +#if 0 // The Mac version of wxExecute(wxString& ...) crashes if there is a space in the path + strExecute = wxT("\""); + strExecute += wxT(buf); + strExecute += wxT("/Contents/Resources/boinc\" -redirectio -launched_by_manager"); + m_lBOINCCoreProcessId = ::wxExecute(strExecute); +#else // Use wxExecute(wxChar **argv ...) instead of wxExecute(wxString& ...) + strcat(buf, "/Contents/Resources/boinc"); + argv[0] = buf; + argv[1] = "-redirectio"; + argv[2] = "-launched_by_manager"; + argv[3] = NULL; +#ifdef SANDBOX + if (! g_use_sandbox) { + argv[3] = "-insecure"; + argv[4] = NULL; + } +#endif + // Under wxMac-2.8.0, wxExecute starts a separate thread to wait for child's termination. + // That wxProcessTerminationThread uses a huge amount of processor time (about 11% of one + // CPU on 2GHz Intel Dual-Core Mac). +// m_lBOINCCoreProcessId = ::wxExecute(argv); + run_program("/Library/Application Support/BOINC Data", buf, argv[3] ? 4 : 3, argv, 0.0, m_lBOINCCoreProcessId); +#endif + } else { + buf[0] = '\0'; + } + } + +#else // Unix based systems + + // copy the path to the boinmgr from argv[0] + strExecute = wxString((const char*)wxGetApp().argv[0], wxConvUTF8); + + // Append boinc.exe to the end of the strExecute string and get ready to rock + strExecute += wxT("/boinc -redirectio -launched_by_manager"); + if (! g_use_sandbox) + strExecute += wxT(" -insecure"); + m_lBOINCCoreProcessId = ::wxExecute(strExecute); + +#endif + + if (0 != m_lBOINCCoreProcessId) { + m_bBOINCStartedByManager = true; + bReturnValue = true; + } + } + + return bReturnValue; +} + + +#if defined(__WXMSW__) + +void CBOINCClientManager::ShutdownBOINCCore() { + wxLogTrace(wxT("Function Start/End"), wxT("CBOINCClientManager::ShutdownBOINCCore - Function Begin")); + + CMainDocument* pDoc = wxGetApp().GetDocument(); + wxInt32 iCount = 0; + DWORD dwExitCode = 0; + bool bClientQuit = false; + wxString strConnectedCompter = wxEmptyString; + wxString strPassword = wxEmptyString; + + wxASSERT(pDoc); + wxASSERT(wxDynamicCast(pDoc, CMainDocument)); + + if (m_bBOINCStartedByManager) { + pDoc->GetConnectedComputerName(strConnectedCompter); + if (!pDoc->IsComputerNameLocal(strConnectedCompter)) { + RPC_CLIENT rpc; + if (!rpc.init("localhost")) { + pDoc->m_pNetworkConnection->GetLocalPassword(strPassword); + rpc.authorize((const char*)strPassword.mb_str()); + if (GetExitCodeProcess(m_hBOINCCoreProcess, &dwExitCode)) { + if (STILL_ACTIVE == dwExitCode) { + rpc.quit(); + for (iCount = 0; iCount <= 10; iCount++) { + if (!bClientQuit && GetExitCodeProcess(m_hBOINCCoreProcess, &dwExitCode)) { + if (STILL_ACTIVE != dwExitCode) { + wxLogTrace(wxT("Function Status"), wxT("CBOINCClientManager::ShutdownBOINCCore - (localhost) Application Exit Detected")); + bClientQuit = true; + break; + } + } + wxLogTrace(wxT("Function Status"), wxT("CBOINCClientManager::ShutdownBOINCCore - (localhost) Application Exit NOT Detected, Sleeping...")); + ::wxSleep(1); + } + } + } + } + rpc.close(); + } else { + if (GetExitCodeProcess(m_hBOINCCoreProcess, &dwExitCode)) { + if (STILL_ACTIVE == dwExitCode) { + pDoc->CoreClientQuit(); + for (iCount = 0; iCount <= 10; iCount++) { + if (!bClientQuit && GetExitCodeProcess(m_hBOINCCoreProcess, &dwExitCode)) { + if (STILL_ACTIVE != dwExitCode) { + wxLogTrace(wxT("Function Status"), wxT("CBOINCClientManager::ShutdownBOINCCore - Application Exit Detected")); + bClientQuit = true; + break; + } + } + wxLogTrace(wxT("Function Status"), wxT("CBOINCClientManager::ShutdownBOINCCore - Application Exit NOT Detected, Sleeping...")); + ::wxSleep(1); + } + } + } + } + + if (!bClientQuit) { + ::wxKill(m_lBOINCCoreProcessId); + } + } + + wxLogTrace(wxT("Function Start/End"), wxT("CBOINCClientManager::ShutdownBOINCCore - Function End")); +} + +#elif defined(__WXMAC__) + +static char * PersistentFGets(char *buf, size_t buflen, FILE *f) { + char *p = buf; + size_t len = buflen; + size_t datalen = 0; + + *buf = '\0'; + while (datalen < (buflen - 1)) { + fgets(p, len, f); + if (feof(f)) break; + if (ferror(f) && (errno != EINTR)) break; + if (strchr(buf, '\n')) break; + datalen = strlen(buf); + p = buf + datalen; + len -= datalen; + } + return (buf[0] ? buf : NULL); +} + +bool CBOINCClientManager::ProcessExists(pid_t thePID) +{ + FILE *f; + char buf[256]; + pid_t aPID; + + f = popen("ps -a -x -c -o pid,state", "r"); + if (f == NULL) + return false; + + while (PersistentFGets(buf, sizeof(buf), f)) { + aPID = atol(buf); + if (aPID == thePID) { + if (strchr(buf, 'Z')) // A 'zombie', stopped but waiting + break; // for us (its parent) to quit + pclose(f); + return true; + } + } + pclose(f); + return false; +} + +// wxProcess::Exists and wxKill are unimplemented in WxMac-2.6.0 +void CBOINCClientManager::ShutdownBOINCCore() { + CMainDocument* pDoc = wxGetApp().GetDocument(); + wxInt32 iCount = 0; + wxString strConnectedCompter = wxEmptyString; + wxString strPassword = wxEmptyString; + + wxASSERT(pDoc); + wxASSERT(wxDynamicCast(pDoc, CMainDocument)); + + if (m_bBOINCStartedByManager) { + pDoc->GetConnectedComputerName(strConnectedCompter); + if (!pDoc->IsComputerNameLocal(strConnectedCompter)) { + RPC_CLIENT rpc; + if (!rpc.init("localhost")) { + pDoc->m_pNetworkConnection->GetLocalPassword(strPassword); + rpc.authorize((const char*)strPassword.mb_str()); + if (ProcessExists(m_lBOINCCoreProcessId)) { + rpc.quit(); + for (iCount = 0; iCount <= 10; iCount++) { + if (!ProcessExists(m_lBOINCCoreProcessId)) + return; + ::wxSleep(1); + } + } + } + rpc.close(); + } else { + if (ProcessExists(m_lBOINCCoreProcessId)) { + pDoc->CoreClientQuit(); + for (iCount = 0; iCount <= 10; iCount++) { + if (!ProcessExists(m_lBOINCCoreProcessId)) + return; + + ::wxSleep(1); + } + } + } + + // Client did not quit after 10 seconds so kill it + kill(m_lBOINCCoreProcessId, SIGKILL); + } +} + +#else + +void CBOINCClientManager::ShutdownBOINCCore() { + CMainDocument* pDoc = wxGetApp().GetDocument(); + wxInt32 iCount = 0; + bool bClientQuit = false; + wxString strConnectedCompter = wxEmptyString; + wxString strPassword = wxEmptyString; + + wxASSERT(pDoc); + wxASSERT(wxDynamicCast(pDoc, CMainDocument)); + + if (m_bBOINCStartedByManager) { + pDoc->GetConnectedComputerName(strConnectedCompter); + if (!pDoc->IsComputerNameLocal(strConnectedCompter)) { + RPC_CLIENT rpc; + if (!rpc.init("localhost")) { + pDoc->m_pNetworkConnection->GetLocalPassword(strPassword); + rpc.authorize((const char*)strPassword.mb_str()); + if (wxProcess::Exists(m_lBOINCCoreProcessId)) { + rpc.quit(); + for (iCount = 0; iCount <= 10; iCount++) { + if (!bClientQuit && !wxProcess::Exists(m_lBOINCCoreProcessId)) { + bClientQuit = true; + break; + } + ::wxSleep(1); + } + } + } + rpc.close(); + } else { + if (wxProcess::Exists(m_lBOINCCoreProcessId)) { + pDoc->CoreClientQuit(); + for (iCount = 0; iCount <= 10; iCount++) { + if (!bClientQuit && !wxProcess::Exists(m_lBOINCCoreProcessId)) { + bClientQuit = true; + break; + } + ::wxSleep(1); + } + } + } + + if (!bClientQuit) { + ::wxKill(m_lBOINCCoreProcessId); + } + } +} + +#endif + diff --git a/clientgui/BOINCClientManager.h b/clientgui/BOINCClientManager.h new file mode 100644 index 0000000000..f7b0a71d72 --- /dev/null +++ b/clientgui/BOINCClientManager.h @@ -0,0 +1,62 @@ +// Berkeley Open Infrastructure for Network Computing +// http://boinc.berkeley.edu +// Copyright (C) 2005 University of California +// +// This is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; +// either version 2.1 of the License, or (at your option) any later version. +// +// This software is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU Lesser General Public License for more details. +// +// To view the GNU Lesser General Public License visit +// http://www.gnu.org/copyleft/lesser.html +// or write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +#ifndef _BOINCCLIENTMANAGER_H_ +#define _BOINCCLIENTMANAGER_H_ + +#if defined(__GNUG__) && !defined(__APPLE__) +#pragma interface "BOINCClientManager.cpp" +#endif + + +class CBOINCClientManager : public wxObject +{ +public: + + CBOINCClientManager(); + ~CBOINCClientManager(); + + bool AutoRestart(); + + bool IsSystemBooting(); + bool IsBOINCDaemon(); + + bool IsBOINCCoreRunning(); + bool StartupBOINCCore(); + void ShutdownBOINCCore(); +#ifdef __WXMAC__ + bool ProcessExists(pid_t thePID); + static OSErr QuitAppleEventHandler( const AppleEvent *appleEvt, AppleEvent* reply, UInt32 refcon ); +#endif + +protected: + + bool m_bBOINCStartedByManager; + bool m_bClientRunningAsDaemon; + int m_lBOINCCoreProcessId; + +#ifdef __WXMSW__ + HANDLE m_hBOINCCoreProcess; +#endif + +}; + + +#endif + diff --git a/clientgui/BOINCGUIApp.cpp b/clientgui/BOINCGUIApp.cpp index 0db01267eb..315b6cc9c1 100644 --- a/clientgui/BOINCGUIApp.cpp +++ b/clientgui/BOINCGUIApp.cpp @@ -44,6 +44,7 @@ #include "BOINCGUIApp.h" #include "SkinManager.h" #include "MainDocument.h" +#include "BOINCClientManager.h" #include "BOINCTaskBar.h" #include "BOINCBaseFrame.h" #include "AdvancedFrame.h" @@ -55,20 +56,12 @@ static bool s_bSkipExitConfirmation = false; #ifdef __WXMSW__ -EXTERN_C BOOL IsBOINCServiceInstalled(); -EXTERN_C BOOL IsBOINCServiceStarting(); -EXTERN_C BOOL IsBOINCServiceRunning(); -EXTERN_C BOOL IsBOINCServiceStopping(); -EXTERN_C BOOL IsBOINCServiceStopped(); -EXTERN_C BOOL StartBOINCService(); -EXTERN_C BOOL StopBOINCService(); EXTERN_C BOOL ClientLibraryStartup(); EXTERN_C void ClientLibraryShutdown(); -EXTERN_C int BOINCIsNetworkAlive(long* lpdwFlags); -EXTERN_C int BOINCIsNetworkAlwaysOnline(); EXTERN_C DWORD BOINCGetIdleTickCount(); #endif + IMPLEMENT_APP(CBOINCGUIApp) IMPLEMENT_DYNAMIC_CLASS(CBOINCGUIApp, wxApp) @@ -76,7 +69,6 @@ IMPLEMENT_DYNAMIC_CLASS(CBOINCGUIApp, wxApp) bool CBOINCGUIApp::OnInit() { // Setup variables with default values - m_bBOINCStartedByManager = false; m_strBOINCArguments = wxEmptyString; m_strBOINCMGRRootDirectory = wxEmptyString; m_pLocale = NULL; @@ -86,17 +78,14 @@ bool CBOINCGUIApp::OnInit() { m_pTaskBarIcon = NULL; #ifdef __WXMAC__ m_pMacSystemMenu = NULL; - m_bClientRunningAsDaemon = false; printf("Using %s.\n", wxVERSION_STRING); // For debugging #endif m_bGUIVisible = true; m_strDefaultWindowStation = wxEmptyString; m_strDefaultDesktop = wxEmptyString; m_strDefaultDisplay = wxEmptyString; - m_lBOINCCoreProcessId = 0; m_iGUISelected = BOINC_SIMPLEGUI; #ifdef __WXMSW__ - m_hBOINCCoreProcess = NULL; m_hClientLibraryDll = NULL; #endif @@ -358,16 +347,6 @@ bool CBOINCGUIApp::OnInit() { #endif } -#ifdef __WXMAC__ - // When running BOINC Client as a daemon / service, the menubar icon is sometimes - // unresponsive to mouse clicks if we create it before connecting to the Client. - bool m_bClientRunningAsDaemon = (TickCount() < (120*60)) && // If system has been up for less than 2 minutes - ( boinc_file_exists("/Library/LaunchDaemons/edu.berkeley.boinc.plist") || // New-style daemon uses launchd - boinc_file_exists("/Library/StartupItems/boinc/boinc") ); // Old-style daemon uses StartupItem - - if (m_bClientRunningAsDaemon) StartupBOINCCore(); -#endif - // Initialize the task bar icon #if defined(__WXMSW__) || defined(__WXMAC__) m_pTaskBarIcon = new CTaskBarIcon( @@ -385,11 +364,6 @@ bool CBOINCGUIApp::OnInit() { // Startup the System Idle Detection code ClientLibraryStartup(); -#ifdef __WXMAC__ - if (! m_bClientRunningAsDaemon) -#endif - StartupBOINCCore(); - #ifdef __WXMAC__ s_bSkipExitConfirmation = false; AEInstallEventHandler( kCoreEventClass, kAEQuitApplication, NewAEEventHandlerUPP((AEEventHandlerProcPtr)QuitAppleEventHandler), 0, false ); @@ -442,9 +416,6 @@ bool CBOINCGUIApp::OnInit() { int CBOINCGUIApp::OnExit() { - // Detect if we need to stop the BOINC Core Client due to configuration - ShutdownBOINCCore(); - // Shutdown the System Idle Detection code ClientLibraryShutdown(); @@ -548,320 +519,7 @@ void CBOINCGUIApp::InitSupportedLanguages() { } -bool CBOINCGUIApp::AutoRestartBOINC() { - if (!IsBOINCCoreRunning() && m_bBOINCStartedByManager) { - StartupBOINCCore(); - } - return true; -} - - -bool CBOINCGUIApp::IsBOINCCoreRunning() { - wxLogTrace(wxT("Function Start/End"), wxT("CBOINCGUIApp::IsBOINCCoreRunning - Function Begin")); - - int retval; - bool running = false; - HOST_INFO hostinfo; - RPC_CLIENT rpc; - -#ifdef __WXMSW__ - - if (IsBOINCServiceInstalled()) { - running = (FALSE != IsBOINCServiceStarting()) || (FALSE != IsBOINCServiceRunning()); - } else { - retval = rpc.init("localhost"); // synchronous is OK since local - wxLogTrace(wxT("Function Status"), wxT("CBOINCGUIApp::IsBOINCCoreRunning - Connecting to core client returned '%d'"), retval); - retval = rpc.get_host_info(hostinfo); - wxLogTrace(wxT("Function Status"), wxT("CBOINCGUIApp::IsBOINCCoreRunning - Requesting host info... retval '%d'"), retval); - running = (retval == 0); - rpc.close(); - } - -#elif defined __WXMAC__ - // If set up to run as a daemon, allow time for daemon to start up - for (int i=0; i<10; i++) { - retval = rpc.init("localhost"); // synchronous is OK since local - retval = rpc.get_host_info(hostinfo); - running = (retval == 0); - rpc.close(); - if (running) break; - if (! m_bClientRunningAsDaemon) break; - sleep(1); - } -#else - retval = rpc.init("localhost"); // synchronous is OK since local - retval = rpc.get_host_info(hostinfo); - running = (retval == 0); - rpc.close(); -#endif - - wxLogTrace(wxT("Function Start/End"), wxT("CBOINCGUIApp::IsBOINCCoreRunning - Function End")); - return running; -} - - -void CBOINCGUIApp::StartupBOINCCore() { - if (!IsBOINCCoreRunning()) { - wxString strExecute = wxEmptyString; - -#if defined(__WXMSW__) - LPTSTR szExecute = NULL; - LPTSTR szDataDirectory = NULL; - - // Append boinc.exe to the end of the strExecute string and get ready to rock - strExecute.Printf( - wxT("\"%s\\boinc.exe\" -redirectio -launched_by_manager %s"), - GetRootDirectory().c_str(), - m_strBOINCArguments.c_str() - ); - - PROCESS_INFORMATION pi; - STARTUPINFO si; - BOOL bProcessStarted; - - memset(&pi, 0, sizeof(pi)); - memset(&si, 0, sizeof(si)); - - si.cb = sizeof(si); - si.dwFlags = STARTF_USESHOWWINDOW; - si.wShowWindow = SW_HIDE; - - szExecute = (LPTSTR)strExecute.c_str(); - if (GetDataDirectory().empty()) { - szDataDirectory = NULL; - } else { - szDataDirectory = (LPTSTR)GetDataDirectory().c_str(); - } - - bProcessStarted = CreateProcess( - NULL, - szExecute, - NULL, - NULL, - FALSE, - CREATE_NEW_PROCESS_GROUP|CREATE_NO_WINDOW, - NULL, - szDataDirectory, - &si, - &pi - ); - if (bProcessStarted) { - m_lBOINCCoreProcessId = pi.dwProcessId; - m_hBOINCCoreProcess = pi.hProcess; - } - -#elif defined(__WXMAC__) - - { - wxChar buf[1024]; - wxChar *argv[5]; - ProcessSerialNumber ourPSN; - FSRef ourFSRef; - OSErr err; - - // Get the full path to core client inside this application's bundle - err = GetCurrentProcess (&ourPSN); - if (err == noErr) { - err = GetProcessBundleLocation(&ourPSN, &ourFSRef); - } - if (err == noErr) { - err = FSRefMakePath (&ourFSRef, (UInt8*)buf, sizeof(buf)); - } - if (err == noErr) { -#if 0 // The Mac version of wxExecute(wxString& ...) crashes if there is a space in the path - strExecute = wxT("\""); - strExecute += wxT(buf); - strExecute += wxT("/Contents/Resources/boinc\" -redirectio -launched_by_manager"); - m_lBOINCCoreProcessId = ::wxExecute(strExecute); -#else // Use wxExecute(wxChar **argv ...) instead of wxExecute(wxString& ...) - strcat(buf, "/Contents/Resources/boinc"); - argv[0] = buf; - argv[1] = "-redirectio"; - argv[2] = "-launched_by_manager"; - argv[3] = NULL; -#ifdef SANDBOX - if (! g_use_sandbox) { - argv[3] = "-insecure"; - argv[4] = NULL; - } -#endif - // Under wxMac-2.8.0, wxExecute starts a separate thread to wait for child's termination. - // That wxProcessTerminationThread uses a huge amount of processor time (about 11% of one - // CPU on 2GHz Intel Dual-Core Mac). -// m_lBOINCCoreProcessId = ::wxExecute(argv); - run_program("/Library/Application Support/BOINC Data", buf, argv[3] ? 4 : 3, argv, 0.0, m_lBOINCCoreProcessId); -#endif - } else { - buf[0] = '\0'; - } - } - -#else // Unix based systems - - // copy the path to the boinmgr from argv[0] - strExecute = wxString((const char*)wxGetApp().argv[0], wxConvUTF8); - - // Append boinc.exe to the end of the strExecute string and get ready to rock - strExecute += wxT("/boinc -redirectio -launched_by_manager"); - if (! g_use_sandbox) - strExecute += wxT(" -insecure"); - m_lBOINCCoreProcessId = ::wxExecute(strExecute); - -#endif - - if (0 != m_lBOINCCoreProcessId) { - m_bBOINCStartedByManager = true; - } - } -} - - -#if defined(__WXMSW__) - -void CBOINCGUIApp::ShutdownBOINCCore() { - wxLogTrace(wxT("Function Start/End"), wxT("CBOINCGUIApp::ShutdownBOINCCore - Function Begin")); - - wxInt32 iCount = 0; - DWORD dwExitCode = 0; - bool bClientQuit = false; - wxString strConnectedCompter = wxEmptyString; - wxString strPassword = wxEmptyString; - - if (m_bBOINCStartedByManager) { - m_pDocument->GetConnectedComputerName(strConnectedCompter); - if (!m_pDocument->IsComputerNameLocal(strConnectedCompter)) { - RPC_CLIENT rpc; - if (!rpc.init("localhost")) { - m_pDocument->m_pNetworkConnection->GetLocalPassword(strPassword); - rpc.authorize((const char*)strPassword.mb_str()); - if (GetExitCodeProcess(m_hBOINCCoreProcess, &dwExitCode)) { - if (STILL_ACTIVE == dwExitCode) { - rpc.quit(); - for (iCount = 0; iCount <= 10; iCount++) { - if (!bClientQuit && GetExitCodeProcess(m_hBOINCCoreProcess, &dwExitCode)) { - if (STILL_ACTIVE != dwExitCode) { - wxLogTrace(wxT("Function Status"), wxT("CBOINCGUIApp::ShutdownBOINCCore - (localhost) Application Exit Detected")); - bClientQuit = true; - break; - } - } - wxLogTrace(wxT("Function Status"), wxT("CBOINCGUIApp::ShutdownBOINCCore - (localhost) Application Exit NOT Detected, Sleeping...")); - ::wxSleep(1); - } - } - } - } - rpc.close(); - } else { - if (GetExitCodeProcess(m_hBOINCCoreProcess, &dwExitCode)) { - if (STILL_ACTIVE == dwExitCode) { - m_pDocument->CoreClientQuit(); - for (iCount = 0; iCount <= 10; iCount++) { - if (!bClientQuit && GetExitCodeProcess(m_hBOINCCoreProcess, &dwExitCode)) { - if (STILL_ACTIVE != dwExitCode) { - wxLogTrace(wxT("Function Status"), wxT("CBOINCGUIApp::ShutdownBOINCCore - Application Exit Detected")); - bClientQuit = true; - break; - } - } - wxLogTrace(wxT("Function Status"), wxT("CBOINCGUIApp::ShutdownBOINCCore - Application Exit NOT Detected, Sleeping...")); - ::wxSleep(1); - } - } - } - } - - if (!bClientQuit) { - ::wxKill(m_lBOINCCoreProcessId); - } - } - - wxLogTrace(wxT("Function Start/End"), wxT("CBOINCGUIApp::ShutdownBOINCCore - Function End")); -} - -#elif defined(__WXMAC__) - -static char * PersistentFGets(char *buf, size_t buflen, FILE *f) { - char *p = buf; - size_t len = buflen; - size_t datalen = 0; - - *buf = '\0'; - while (datalen < (buflen - 1)) { - fgets(p, len, f); - if (feof(f)) break; - if (ferror(f) && (errno != EINTR)) break; - if (strchr(buf, '\n')) break; - datalen = strlen(buf); - p = buf + datalen; - len -= datalen; - } - return (buf[0] ? buf : NULL); -} - -bool CBOINCGUIApp::ProcessExists(pid_t thePID) -{ - FILE *f; - char buf[256]; - pid_t aPID; - - f = popen("ps -a -x -c -o pid,state", "r"); - if (f == NULL) - return false; - - while (PersistentFGets(buf, sizeof(buf), f)) { - aPID = atol(buf); - if (aPID == thePID) { - if (strchr(buf, 'Z')) // A 'zombie', stopped but waiting - break; // for us (its parent) to quit - pclose(f); - return true; - } - } - pclose(f); - return false; -} - -// wxProcess::Exists and wxKill are unimplemented in WxMac-2.6.0 -void CBOINCGUIApp::ShutdownBOINCCore() { - wxInt32 iCount = 0; - wxString strConnectedCompter = wxEmptyString; - wxString strPassword = wxEmptyString; - - if (m_bBOINCStartedByManager) { - m_pDocument->GetConnectedComputerName(strConnectedCompter); - if (!m_pDocument->IsComputerNameLocal(strConnectedCompter)) { - RPC_CLIENT rpc; - if (!rpc.init("localhost")) { - m_pDocument->m_pNetworkConnection->GetLocalPassword(strPassword); - rpc.authorize((const char*)strPassword.mb_str()); - if (ProcessExists(m_lBOINCCoreProcessId)) { - rpc.quit(); - for (iCount = 0; iCount <= 10; iCount++) { - if (!ProcessExists(m_lBOINCCoreProcessId)) - return; - ::wxSleep(1); - } - } - } - rpc.close(); - } else { - if (ProcessExists(m_lBOINCCoreProcessId)) { - m_pDocument->CoreClientQuit(); - for (iCount = 0; iCount <= 10; iCount++) { - if (!ProcessExists(m_lBOINCCoreProcessId)) - return; - - ::wxSleep(1); - } - } - } - - // Client did not quit after 10 seconds so kill it - kill(m_lBOINCCoreProcessId, SIGKILL); - } -} - +#ifdef __WXMAC__ // Set s_bSkipExitConfirmation to true if cancelled because of logging out or shutting down OSErr CBOINCGUIApp::QuitAppleEventHandler( const AppleEvent *appleEvt, AppleEvent* reply, UInt32 refcon ) { @@ -911,52 +569,6 @@ OSErr CBOINCGUIApp::QuitAppleEventHandler( const AppleEvent *appleEvt, AppleEven return wxGetApp().MacHandleAEQuit((AppleEvent*)appleEvt, reply); } -#else - -void CBOINCGUIApp::ShutdownBOINCCore() { - wxInt32 iCount = 0; - bool bClientQuit = false; - wxString strConnectedCompter = wxEmptyString; - wxString strPassword = wxEmptyString; - - if (m_bBOINCStartedByManager) { - m_pDocument->GetConnectedComputerName(strConnectedCompter); - if (!m_pDocument->IsComputerNameLocal(strConnectedCompter)) { - RPC_CLIENT rpc; - if (!rpc.init("localhost")) { - m_pDocument->m_pNetworkConnection->GetLocalPassword(strPassword); - rpc.authorize((const char*)strPassword.mb_str()); - if (wxProcess::Exists(m_lBOINCCoreProcessId)) { - rpc.quit(); - for (iCount = 0; iCount <= 10; iCount++) { - if (!bClientQuit && !wxProcess::Exists(m_lBOINCCoreProcessId)) { - bClientQuit = true; - break; - } - ::wxSleep(1); - } - } - } - rpc.close(); - } else { - if (wxProcess::Exists(m_lBOINCCoreProcessId)) { - m_pDocument->CoreClientQuit(); - for (iCount = 0; iCount <= 10; iCount++) { - if (!bClientQuit && !wxProcess::Exists(m_lBOINCCoreProcessId)) { - bClientQuit = true; - break; - } - ::wxSleep(1); - } - } - } - - if (!bClientQuit) { - ::wxKill(m_lBOINCCoreProcessId); - } - } -} - #endif @@ -1068,12 +680,15 @@ bool CBOINCGUIApp::SetActiveGUI(int iGUISelection, bool bShowWindow) { int CBOINCGUIApp::ConfirmExit() { CSkinAdvanced* pSkinAdvanced = wxGetApp().GetSkinManager()->GetAdvanced(); + CMainDocument* pDoc = wxGetApp().GetDocument(); wxString strTitle; - + + wxASSERT(pDoc); wxASSERT(pSkinAdvanced); + wxASSERT(wxDynamicCast(pDoc, CMainDocument)); wxASSERT(wxDynamicCast(pSkinAdvanced, CSkinAdvanced)); - if (!m_bBOINCStartedByManager) + if (pDoc->m_pClientManager->IsBOINCDaemon()) return 1; // Don't run dialog if exiting manager won't shut down Client or its tasks if (!m_iDisplayExitWarning) diff --git a/clientgui/BOINCGUIApp.h b/clientgui/BOINCGUIApp.h index 43b79d9779..600e5d2354 100644 --- a/clientgui/BOINCGUIApp.h +++ b/clientgui/BOINCGUIApp.h @@ -52,11 +52,7 @@ protected: void InitSupportedLanguages(); - bool IsBOINCCoreRunning(); - void StartupBOINCCore(); - void ShutdownBOINCCore(); #ifdef __WXMAC__ - bool ProcessExists(pid_t thePID); static OSErr QuitAppleEventHandler( const AppleEvent *appleEvt, AppleEvent* reply, UInt32 refcon ); #endif @@ -73,10 +69,8 @@ protected: CTaskBarIcon* m_pTaskBarIcon; #ifdef __WXMAC__ CMacSystemMenu* m_pMacSystemMenu; - bool m_bClientRunningAsDaemon; #endif - bool m_bBOINCStartedByManager; wxString m_strBOINCMGRRootDirectory; wxString m_strBOINCMGRDataDirectory; wxString m_strBOINCArguments; @@ -86,10 +80,7 @@ protected: bool m_bGUIVisible; int m_iGUISelected; - int m_lBOINCCoreProcessId; - #ifdef __WXMSW__ - HANDLE m_hBOINCCoreProcess; HINSTANCE m_hClientLibraryDll; #endif @@ -105,8 +96,6 @@ public: bool OnInit(); - bool AutoRestartBOINC(); - int UpdateSystemIdleDetection(); int StartBOINCScreensaverTest(); @@ -115,6 +104,7 @@ public: CSkinManager* GetSkinManager() { return m_pSkinManager; } CBOINCBaseFrame* GetFrame() { return m_pFrame; } CMainDocument* GetDocument() { return m_pDocument; } + wxString GetArguments() { return m_strBOINCArguments; } wxString GetRootDirectory() { return m_strBOINCMGRRootDirectory; } wxString GetDataDirectory() { return m_strBOINCMGRDataDirectory; } #if defined(__WXMSW__) || defined(__WXMAC__) diff --git a/clientgui/MainDocument.cpp b/clientgui/MainDocument.cpp index 1ac3a0379d..138faa88c4 100644 --- a/clientgui/MainDocument.cpp +++ b/clientgui/MainDocument.cpp @@ -29,8 +29,9 @@ #include "BOINCGUIApp.h" #include "BOINCBaseFrame.h" #include "MainDocument.h" -#ifdef _WIN32 -#else +#include "BOINCClientManager.h" + +#ifndef _WIN32 #include #endif @@ -313,6 +314,7 @@ IMPLEMENT_DYNAMIC_CLASS(CMainDocument, wxObject) CMainDocument::CMainDocument() { + #ifdef __WIN32__ int retval; WSADATA wsdata; @@ -323,6 +325,8 @@ CMainDocument::CMainDocument() { } #endif + m_bClientStartCheckCompleted = false; + m_fProjectTotalResourceShare = 0.0; m_iMessageSequenceNumber = 0; @@ -347,6 +351,86 @@ CMainDocument::~CMainDocument() { } +int CMainDocument::OnInit() { + int iRetVal = -1; + + m_pNetworkConnection = new CNetworkConnection(this); + wxASSERT(m_pNetworkConnection); + + m_pClientManager = new CBOINCClientManager(); + wxASSERT(m_pClientManager); + + return iRetVal; +} + + +int CMainDocument::OnExit() { + int iRetVal = 0; + + if (m_pClientManager) { + m_pClientManager->ShutdownBOINCCore(); + + delete m_pClientManager; + m_pClientManager = NULL; + } + + if (m_pNetworkConnection) { + delete m_pNetworkConnection; + m_pNetworkConnection = NULL; + } + + return iRetVal; +} + + +int CMainDocument::OnPoll() { + int iRetVal = 0; + + wxASSERT(wxDynamicCast(m_pClientManager, CBOINCClientManager)); + wxASSERT(wxDynamicCast(m_pNetworkConnection, CNetworkConnection)); + + if (!m_bClientStartCheckCompleted) { + m_bClientStartCheckCompleted = true; + + CBOINCBaseFrame* pFrame = wxGetApp().GetFrame(); + wxASSERT(wxDynamicCast(pFrame, CBOINCBaseFrame)); + + pFrame->UpdateStatusText(_("Starting client services; please wait...")); + + if (m_pClientManager->StartupBOINCCore()) { + Connect(wxT("localhost"), wxEmptyString, TRUE, TRUE); + } else { + m_pNetworkConnection->ForceDisconnect(); + pFrame->ShowDaemonStartFailedAlert(); + } + + pFrame->UpdateStatusText(wxEmptyString); + } + + // Check connection state, connect if needed. + m_pNetworkConnection->Poll(); + + // Every 10 seconds, kill any running graphics apps + // whose associated worker tasks are no longer running + wxTimeSpan ts(wxDateTime::Now() - m_dtKillInactiveGfxTimestamp); + if (ts.GetSeconds() > 10) { + m_dtKillInactiveGfxTimestamp = wxDateTime::Now(); + KillInactiveGraphicsApps(); + } + + return iRetVal; +} + + +int CMainDocument::OnRefreshState() { + if (IsConnected()) { + CachedStateUpdate(); + } + + return 0; +} + + int CMainDocument::CachedStateUpdate() { wxLogTrace(wxT("Function Start/End"), wxT("CMainDocument::CachedStateUpdate - Function Begin")); @@ -380,56 +464,6 @@ int CMainDocument::CachedStateUpdate() { } -int CMainDocument::OnInit() { - int iRetVal = -1; - - // start the connect management thread - m_pNetworkConnection = new CNetworkConnection(this); - - return iRetVal; -} - - -int CMainDocument::OnExit() { - int iRetVal = 0; - - if (m_pNetworkConnection) { - delete m_pNetworkConnection; - m_pNetworkConnection = NULL; - } - - return iRetVal; -} - - -int CMainDocument::OnPoll() { - int iRetVal = 0; - - if (m_pNetworkConnection) { - m_pNetworkConnection->Poll(); - } - - // Every 10 seconds, kill any running graphics apps - // whose associated worker tasks are no longer running - wxTimeSpan ts(wxDateTime::Now() - m_dtKillInactiveGfxTimestamp); - if (ts.GetSeconds() > 10) { - m_dtKillInactiveGfxTimestamp = wxDateTime::Now(); - KillInactiveGraphicsApps(); - } - - return iRetVal; -} - - -int CMainDocument::OnRefreshState() { - if (IsConnected()) { - CachedStateUpdate(); - } - - return 0; -} - - int CMainDocument::ResetState() { rpc.close(); state.clear(); @@ -1083,7 +1117,7 @@ void CMainDocument::KillInactiveGraphicsApps() void CMainDocument::KillAllRunningGraphicsApps() { - int i, n; + size_t i, n; std::vector::iterator gfx_app_iter; n = m_running_gfx_apps.size(); @@ -1238,7 +1272,7 @@ int CMainDocument::CachedMessageUpdate() { goto done; } if (messages.messages.size() != 0) { - int last_ind = messages.messages.size()-1; + size_t last_ind = messages.messages.size()-1; m_iMessageSequenceNumber = messages.messages[last_ind]->seqno; } } else { diff --git a/clientgui/MainDocument.h b/clientgui/MainDocument.h index 66da33c00d..7af7c6f7a6 100644 --- a/clientgui/MainDocument.h +++ b/clientgui/MainDocument.h @@ -43,6 +43,7 @@ typedef struct { extern bool g_use_sandbox; class CMainDocument; +class CBOINCClientManager; class CNetworkConnection : public wxObject { public: @@ -51,6 +52,7 @@ public: void Poll(); void FireReconnectEvent() { m_bConnectEvent = true; }; + void ForceDisconnect() { m_bForceReconnect = false; m_bReconnectOnError = false; m_bConnectEvent = false; SetStateDisconnected(); }; void ForceReconnect() { m_bForceReconnect = true; SetStateDisconnected(); }; int FrameShutdownDetected(); int GetConnectedComputerName(wxString& strMachine); @@ -101,18 +103,16 @@ public: private: wxDateTime m_dtCachedCCStatusTimestamp; + bool m_bClientStartCheckCompleted; public: - int CachedStateUpdate(); - - CNetworkConnection* m_pNetworkConnection; - int OnInit(); int OnExit(); int OnPoll(); int OnRefreshState(); + int CachedStateUpdate(); int ResetState(); int Connect( @@ -145,6 +145,8 @@ public: bool IsUserAuthorized(); + CNetworkConnection* m_pNetworkConnection; + CBOINCClientManager* m_pClientManager; RPC_CLIENT rpc; CC_STATE state; CC_STATUS status; diff --git a/lib/util.C b/lib/util.C index 9af320605f..28051004ea 100644 --- a/lib/util.C +++ b/lib/util.C @@ -307,7 +307,7 @@ int run_program( NULL, NULL, FALSE, - IDLE_PRIORITY_CLASS, + 0, NULL, dir, &startup_info, diff --git a/win_build/boincmgr_curl.vcproj b/win_build/boincmgr_curl.vcproj index fd81b14b18..4d0cbb7f8c 100644 --- a/win_build/boincmgr_curl.vcproj +++ b/win_build/boincmgr_curl.vcproj @@ -1914,6 +1914,14 @@ RelativePath="..\clientgui\BOINCBaseFrame.h" > + + + +