1
// Berkeley Open Infrastructure for Network Computing
2
// http://boinc.berkeley.edu
3
// Copyright (C) 2005 University of California
5
// This is free software; you can redistribute it and/or
6
// modify it under the terms of the GNU Lesser General Public
7
// License as published by the Free Software Foundation;
8
// either version 2.1 of the License, or (at your option) any later version.
10
// This software is distributed in the hope that it will be useful,
11
// but WITHOUT ANY WARRANTY; without even the implied warranty of
12
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13
// See the GNU Lesser General Public License for more details.
15
// To view the GNU Lesser General Public License visit
16
// http://www.gnu.org/copyleft/lesser.html
17
// or write to the Free Software Foundation, Inc.,
18
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20
#if defined(__GNUG__) && !defined(__APPLE__)
21
#pragma implementation "BOINCClientManager.h"
25
#include "diagnostics.h"
27
#include "BOINCGUIApp.h"
28
#include "MainDocument.h"
29
#include "BOINCBaseFrame.h"
30
#include "AdvancedFrame.h"
31
#include "BOINCClientManager.h"
44
EXTERN_C BOOL IsBOINCServiceInstalled();
45
EXTERN_C BOOL IsBOINCServiceStarting();
46
EXTERN_C BOOL IsBOINCServiceRunning();
47
EXTERN_C BOOL IsBOINCServiceStopping();
48
EXTERN_C BOOL IsBOINCServiceStopped();
49
EXTERN_C BOOL StartBOINCService();
50
EXTERN_C BOOL StopBOINCService();
53
CBOINCClientManager::CBOINCClientManager() {
54
wxLogTrace(wxT("Function Start/End"), wxT("CBOINCClientManager::CBOINCClientManager - Function Begin"));
56
m_bBOINCStartedByManager = false;
57
m_lBOINCCoreProcessId = 0;
60
m_hBOINCCoreProcess = NULL;
63
wxLogTrace(wxT("Function Start/End"), wxT("CBOINCClientManager::CBOINCClientManager - Function End"));
67
CBOINCClientManager::~CBOINCClientManager() {
68
wxLogTrace(wxT("Function Start/End"), wxT("CBOINCClientManager::~CBOINCClientManager - Function Begin"));
70
wxLogTrace(wxT("Function Start/End"), wxT("CBOINCClientManager::~CBOINCClientManager - Function End"));
74
bool CBOINCClientManager::AutoRestart() {
75
if (IsBOINCCoreRunning()) return true;
76
#ifndef __WXMAC__ // Mac can restart Client as a daemon
77
if (! m_bBOINCStartedByManager) return false;
79
m_lBOINCCoreProcessId = 0;
85
bool CBOINCClientManager::IsSystemBooting() {
86
bool bReturnValue = false;
87
#if defined(__WXMSW__)
88
if (GetTickCount() < (1000*60*5)) bReturnValue = true; // If system has been up for less than 5 minutes
89
#elif defined(__WXMAC__)
90
if (TickCount() < (120*60)) bReturnValue = true; // If system has been up for less than 2 minutes
96
int CBOINCClientManager::IsBOINCConfiguredAsDaemon() {
97
bool bReturnValue = false;
98
#if defined(__WXMSW__)
99
if (IsBOINCServiceInstalled()) bReturnValue = 1;
100
#elif defined(__WXMAC__)
101
if ( boinc_file_exists("/Library/LaunchDaemons/edu.berkeley.boinc.plist")) {
102
bReturnValue = NewStyleDaemon; // New-style daemon uses launchd
104
if (boinc_file_exists("/Library/StartupItems/boinc/boinc") ) {
105
bReturnValue = OldStyleDaemon; // Old-style daemon uses StartupItem
112
bool CBOINCClientManager::IsBOINCCoreRunning() {
113
wxLogTrace(wxT("Function Start/End"), wxT("CBOINCClientManager::IsBOINCCoreRunning - Function Begin"));
116
bool running = false;
121
if (IsBOINCServiceInstalled()) {
122
running = (FALSE != IsBOINCServiceStarting()) || (FALSE != IsBOINCServiceRunning());
125
// If set up to run as a daemon, allow time for daemon to start up
126
for (int i=0; i<10; i++) {
127
retval = rpc.init("localhost"); // synchronous is OK since local
128
wxLogTrace(wxT("Function Status"), wxT("CBOINCClientManager::IsBOINCCoreRunning - Connecting to core client returned '%d'"), retval);
129
retval = rpc.get_host_info(hostinfo);
130
wxLogTrace(wxT("Function Status"), wxT("CBOINCClientManager::IsBOINCCoreRunning - Requesting host info... retval '%d'"), retval);
131
running = (retval == 0);
134
if (!IsBOINCConfiguredAsDaemon()) break;
141
wxLogTrace(wxT("Function Status"), wxT("CBOINCClientManager::IsBOINCCoreRunning - Returning '%d'"), retval);
142
wxLogTrace(wxT("Function Start/End"), wxT("CBOINCClientManager::IsBOINCCoreRunning - Function End"));
147
bool CBOINCClientManager::StartupBOINCCore() {
148
wxLogTrace(wxT("Function Start/End"), wxT("CMainDocument::StartupBOINCCore - Function Begin"));
150
bool bReturnValue = false;
151
wxString strExecute = wxEmptyString;
153
if (IsBOINCCoreRunning()) return true;
155
#if defined(__WXMSW__)
156
LPTSTR szExecute = NULL;
157
LPTSTR szDataDirectory = NULL;
159
if (IsBOINCConfiguredAsDaemon()) {
162
m_bBOINCStartedByManager = true;
163
bReturnValue = IsBOINCCoreRunning();
166
// Append boinc.exe to the end of the strExecute string and get ready to rock
168
wxT("\"%s\\boinc.exe\" --redirectio --launched_by_manager %s"),
169
wxGetApp().GetRootDirectory().c_str(),
170
wxGetApp().GetArguments().c_str()
173
PROCESS_INFORMATION pi;
175
BOOL bProcessStarted;
177
memset(&pi, 0, sizeof(pi));
178
memset(&si, 0, sizeof(si));
181
si.dwFlags = STARTF_USESHOWWINDOW;
182
si.wShowWindow = SW_HIDE;
184
szExecute = (LPTSTR)strExecute.c_str();
185
if (wxGetApp().GetDataDirectory().empty()) {
186
szDataDirectory = NULL;
188
szDataDirectory = (LPTSTR)wxGetApp().GetDataDirectory().c_str();
191
wxLogTrace(wxT("Function Status"), wxT("CMainDocument::StartupBOINCCore - szExecute '%s'\n"), szExecute);
192
wxLogTrace(wxT("Function Status"), wxT("CMainDocument::StartupBOINCCore - szDataDirectory '%s'\n"), szDataDirectory);
194
bProcessStarted = CreateProcess(
200
CREATE_NEW_PROCESS_GROUP|CREATE_NO_WINDOW,
206
if (bProcessStarted) {
207
m_lBOINCCoreProcessId = pi.dwProcessId;
208
m_hBOINCCoreProcess = pi.hProcess;
212
#elif defined(__WXMAC__)
216
ProcessSerialNumber ourPSN;
220
if (IsBOINCConfiguredAsDaemon() == NewStyleDaemon) {
221
system ("launchctl load /Library/LaunchDaemons/edu.berkeley.boinc.plist");
222
system ("launchctl start edu.berkeley.boinc");
223
bReturnValue = IsBOINCCoreRunning();
226
// Get the full path to core client inside this application's bundle
227
err = GetCurrentProcess (&ourPSN);
229
err = GetProcessBundleLocation(&ourPSN, &ourFSRef);
232
err = FSRefMakePath (&ourFSRef, (UInt8*)buf, sizeof(buf));
235
#if 0 // The Mac version of wxExecute(wxString& ...) crashes if there is a space in the path
236
strExecute = wxT("\"");
237
strExecute += wxT(buf);
238
strExecute += wxT("/Contents/Resources/boinc\" --redirectio --launched_by_manager");
239
m_lBOINCCoreProcessId = ::wxExecute(strExecute);
240
#else // Use wxExecute(wxChar **argv ...) instead of wxExecute(wxString& ...)
241
strcat(buf, "/Contents/Resources/boinc");
243
argv[1] = "--redirectio";
244
argv[2] = "--launched_by_manager";
247
if (!g_use_sandbox) {
248
argv[3] = "--insecure";
252
// Under wxMac-2.8.0, wxExecute starts a separate thread
253
// to wait for child's termination.
254
// That wxProcessTerminationThread uses a huge amount of processor
255
// time (about 11% of one CPU on 2GHz Intel Dual-Core Mac).
256
// m_lBOINCCoreProcessId = ::wxExecute(argv);
258
"/Library/Application Support/BOINC Data",
259
buf, argv[3] ? 4 : 3, argv, 0.0, m_lBOINCCoreProcessId
267
#else // Unix based systems
269
// Append boinc.exe to the end of the strExecute string and get ready to rock
270
strExecute = ::wxGetCwd() + wxT("/boinc --redirectio --launched_by_manager");
272
wxLogTrace(wxT("Function Status"), wxT("CMainDocument::StartupBOINCCore - szExecute '%s'\n"), strExecute.c_str());
273
wxLogTrace(wxT("Function Status"), wxT("CMainDocument::StartupBOINCCore - szDataDirectory '%s'\n"), ::wxGetCwd().c_str());
275
m_lBOINCCoreProcessId = ::wxExecute(strExecute);
279
if (0 != m_lBOINCCoreProcessId) {
280
m_bBOINCStartedByManager = true;
284
wxLogTrace(wxT("Function Start/End"), wxT("CMainDocument::StartupBOINCCore - Function End"));
289
#if defined(__WXMSW__)
291
void CBOINCClientManager::ShutdownBOINCCore() {
292
wxLogTrace(wxT("Function Start/End"), wxT("CBOINCClientManager::ShutdownBOINCCore - Function Begin"));
294
CMainDocument* pDoc = wxGetApp().GetDocument();
296
DWORD dwExitCode = 0;
297
bool bClientQuit = false;
298
wxString strConnectedCompter = wxEmptyString;
299
wxString strPassword = wxEmptyString;
302
wxASSERT(wxDynamicCast(pDoc, CMainDocument));
304
if (m_bBOINCStartedByManager) {
305
if (IsBOINCConfiguredAsDaemon()) {
309
pDoc->GetConnectedComputerName(strConnectedCompter);
310
if (!pDoc->IsComputerNameLocal(strConnectedCompter)) {
312
if (!rpc.init("localhost")) {
313
pDoc->m_pNetworkConnection->GetLocalPassword(strPassword);
314
rpc.authorize((const char*)strPassword.mb_str());
315
if (GetExitCodeProcess(m_hBOINCCoreProcess, &dwExitCode)) {
316
if (STILL_ACTIVE == dwExitCode) {
318
for (iCount = 0; iCount <= 10; iCount++) {
319
if (!bClientQuit && GetExitCodeProcess(m_hBOINCCoreProcess, &dwExitCode)) {
320
if (STILL_ACTIVE != dwExitCode) {
321
wxLogTrace(wxT("Function Status"), wxT("CBOINCClientManager::ShutdownBOINCCore - (localhost) Application Exit Detected"));
326
wxLogTrace(wxT("Function Status"), wxT("CBOINCClientManager::ShutdownBOINCCore - (localhost) Application Exit NOT Detected, Sleeping..."));
334
if (GetExitCodeProcess(m_hBOINCCoreProcess, &dwExitCode)) {
335
if (STILL_ACTIVE == dwExitCode) {
336
pDoc->CoreClientQuit();
337
for (iCount = 0; iCount <= 10; iCount++) {
338
if (!bClientQuit && GetExitCodeProcess(m_hBOINCCoreProcess, &dwExitCode)) {
339
if (STILL_ACTIVE != dwExitCode) {
340
wxLogTrace(wxT("Function Status"), wxT("CBOINCClientManager::ShutdownBOINCCore - Application Exit Detected"));
345
wxLogTrace(wxT("Function Status"), wxT("CBOINCClientManager::ShutdownBOINCCore - Application Exit NOT Detected, Sleeping..."));
354
::wxKill(m_lBOINCCoreProcessId);
356
m_lBOINCCoreProcessId = 0;
359
wxLogTrace(wxT("Function Start/End"), wxT("CBOINCClientManager::ShutdownBOINCCore - Function End"));
362
#elif defined(__WXMAC__)
364
static char * PersistentFGets(char *buf, size_t buflen, FILE *f) {
370
while (datalen < (buflen - 1)) {
373
if (ferror(f) && (errno != EINTR)) break;
374
if (strchr(buf, '\n')) break;
375
datalen = strlen(buf);
379
return (buf[0] ? buf : NULL);
382
bool CBOINCClientManager::ProcessExists(pid_t thePID)
388
f = popen("ps -a -x -c -o pid,state", "r");
392
while (PersistentFGets(buf, sizeof(buf), f)) {
394
if (aPID == thePID) {
395
if (strchr(buf, 'Z')) // A 'zombie', stopped but waiting
396
break; // for us (its parent) to quit
405
// wxProcess::Exists and wxKill are unimplemented in WxMac-2.6.0
406
void CBOINCClientManager::ShutdownBOINCCore() {
407
CMainDocument* pDoc = wxGetApp().GetDocument();
409
wxString strConnectedCompter = wxEmptyString;
410
wxString strPassword = wxEmptyString;
413
wxASSERT(wxDynamicCast(pDoc, CMainDocument));
415
if (m_bBOINCStartedByManager) {
416
pDoc->GetConnectedComputerName(strConnectedCompter);
417
if (!pDoc->IsComputerNameLocal(strConnectedCompter)) {
419
if (!rpc.init("localhost")) {
420
pDoc->m_pNetworkConnection->GetLocalPassword(strPassword);
421
rpc.authorize((const char*)strPassword.mb_str());
422
if (ProcessExists(m_lBOINCCoreProcessId)) {
424
for (iCount = 0; iCount <= 10; iCount++) {
425
if (!ProcessExists(m_lBOINCCoreProcessId))
433
if (ProcessExists(m_lBOINCCoreProcessId)) {
434
pDoc->CoreClientQuit();
435
for (iCount = 0; iCount <= 10; iCount++) {
436
if (!ProcessExists(m_lBOINCCoreProcessId))
444
// Client did not quit after 10 seconds so kill it
445
kill(m_lBOINCCoreProcessId, SIGKILL);
447
m_lBOINCCoreProcessId = 0;
452
void CBOINCClientManager::ShutdownBOINCCore() {
453
CMainDocument* pDoc = wxGetApp().GetDocument();
455
bool bClientQuit = false;
456
wxString strConnectedCompter = wxEmptyString;
457
wxString strPassword = wxEmptyString;
460
wxASSERT(wxDynamicCast(pDoc, CMainDocument));
462
if (m_bBOINCStartedByManager) {
463
pDoc->GetConnectedComputerName(strConnectedCompter);
464
if (!pDoc->IsComputerNameLocal(strConnectedCompter)) {
466
if (!rpc.init("localhost")) {
467
pDoc->m_pNetworkConnection->GetLocalPassword(strPassword);
468
rpc.authorize((const char*)strPassword.mb_str());
469
if (wxProcess::Exists(m_lBOINCCoreProcessId)) {
471
for (iCount = 0; iCount <= 10; iCount++) {
472
if (!bClientQuit && !wxProcess::Exists(m_lBOINCCoreProcessId)) {
482
if (wxProcess::Exists(m_lBOINCCoreProcessId)) {
483
pDoc->CoreClientQuit();
484
for (iCount = 0; iCount <= 10; iCount++) {
485
if (!bClientQuit && !wxProcess::Exists(m_lBOINCCoreProcessId)) {
495
::wxKill(m_lBOINCCoreProcessId);
1
// This file is part of BOINC.
2
// http://boinc.berkeley.edu
3
// Copyright (C) 2008 University of California
5
// BOINC is free software; you can redistribute it and/or modify it
6
// under the terms of the GNU Lesser General Public License
7
// as published by the Free Software Foundation,
8
// either version 3 of the License, or (at your option) any later version.
10
// BOINC is distributed in the hope that it will be useful,
11
// but WITHOUT ANY WARRANTY; without even the implied warranty of
12
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13
// See the GNU Lesser General Public License for more details.
15
// You should have received a copy of the GNU Lesser General Public License
16
// along with BOINC. If not, see <http://www.gnu.org/licenses/>.
18
#if defined(__GNUG__) && !defined(__APPLE__)
19
#pragma implementation "BOINCClientManager.h"
23
#include "diagnostics.h"
26
#include "BOINCGUIApp.h"
27
#include "SkinManager.h"
28
#include "MainDocument.h"
29
#include "BOINCBaseFrame.h"
30
#include "AdvancedFrame.h"
31
#include "BOINCClientManager.h"
32
#include "error_numbers.h"
35
#include "daemonmgt.h"
40
// Alert user if Client crashes 3 times in 30 minutes
41
#define CLIENT_3_CRASH_MAX_TIME 30
49
#elif defined(__WXMSW__)
52
#include "diagnostics_win.h"
54
extern int diagnostics_get_process_information(PVOID* ppBuffer, PULONG pcbBuffer);
60
CBOINCClientManager::CBOINCClientManager() {
61
wxLogTrace(wxT("Function Start/End"), wxT("CBOINCClientManager::CBOINCClientManager - Function Begin"));
63
m_bBOINCStartedByManager = false;
64
m_lBOINCCoreProcessId = 0;
65
m_fAutoRestart1Time = 0;
66
m_fAutoRestart2Time = 0;
69
m_hBOINCCoreProcess = NULL;
72
wxLogTrace(wxT("Function Start/End"), wxT("CBOINCClientManager::CBOINCClientManager - Function End"));
76
CBOINCClientManager::~CBOINCClientManager() {
77
wxLogTrace(wxT("Function Start/End"), wxT("CBOINCClientManager::~CBOINCClientManager - Function Begin"));
79
wxLogTrace(wxT("Function Start/End"), wxT("CBOINCClientManager::~CBOINCClientManager - Function End"));
83
bool CBOINCClientManager::AutoRestart() {
84
double timeNow, timeDiff;
85
if (IsBOINCCoreRunning()) return true;
86
#if ! (defined(__WXMAC__) || defined(__WXMSW__))
87
// Mac and Windows can restart Client as a daemon, but
88
// Linux may not know Client's location if it didn't start the Client
89
if (!m_bBOINCStartedByManager) return false;
91
// Alert user if Client crashes 3 times in CLIENT_3_CRASH_MAX_TIME
93
timeDiff = timeNow - m_fAutoRestart1Time;
94
if ((timeDiff) < (CLIENT_3_CRASH_MAX_TIME * 60)) {
96
ClientCrashDlg *dlg = new ClientCrashDlg(timeDiff);
98
CBOINCBaseFrame* pFrame = wxGetApp().GetFrame();
99
if (!pFrame->IsShown()) {
102
response = dlg->ShowModal();
104
if (response == wxID_CANCEL) return false;
106
m_fAutoRestart1Time = 0;
107
m_fAutoRestart2Time = 0;
110
m_lBOINCCoreProcessId = 0;
111
m_fAutoRestart1Time = m_fAutoRestart2Time;
112
m_fAutoRestart2Time = timeNow;
118
bool CBOINCClientManager::IsSystemBooting() {
119
bool bReturnValue = false;
120
#if defined(__WXMSW__)
121
if (GetTickCount() < (1000*60*5)) bReturnValue = true; // If system has been up for less than 5 minutes
122
#elif defined(__WXMAC__)
123
if (TickCount() < (120*60)) bReturnValue = true; // If system has been up for less than 2 minutes
129
int CBOINCClientManager::IsBOINCConfiguredAsDaemon() {
130
bool bReturnValue = false;
131
#if defined(__WXMSW__)
132
if (is_daemon_installed()) bReturnValue = 1;
133
#elif defined(__WXMAC__)
134
if ( boinc_file_exists("/Library/LaunchDaemons/edu.berkeley.boinc.plist")) {
135
bReturnValue = NewStyleDaemon; // New-style daemon uses launchd
137
if (boinc_file_exists("/Library/StartupItems/boinc/boinc") ) {
138
bReturnValue = OldStyleDaemon; // Old-style daemon uses StartupItem
145
bool CBOINCClientManager::IsBOINCCoreRunning() {
146
wxLogTrace(wxT("Function Start/End"), wxT("CBOINCClientManager::IsBOINCCoreRunning - Function Begin"));
147
bool running = false;
150
char buf[MAX_PATH] = "";
152
if (is_daemon_installed()) {
153
running = (FALSE != is_daemon_starting()) || (FALSE != is_daemon_running());
155
// Global mutex on Win2k and later
157
if (IsWindows2000Compatible()) {
158
strcpy(buf, "Global\\");
160
strcat( buf, RUN_MUTEX);
162
HANDLE h = CreateMutexA(NULL, true, buf);
163
DWORD err = GetLastError();
164
if ((h==0) || (err == ERROR_ALREADY_EXISTS)) {
171
#elif defined(__WXMAC__)
173
static FILE_LOCK file_lock;
175
sprintf(path, "%s/%s", (const char *)wxGetApp().GetDataDirectory().mb_str(), LOCK_FILE_NAME);
176
if (boinc_file_exists(path)) { // If there is no lock file, core is not running
177
if (file_lock.lock(path)) {
180
file_lock.unlock(path);
184
std::vector<PROCINFO> piv;
187
if (m_lBOINCCoreProcessId) {
188
// Prevent client from being a zombie
189
if (waitpid(m_lBOINCCoreProcessId, 0, WNOHANG) == m_lBOINCCoreProcessId) {
190
m_lBOINCCoreProcessId = 0;
194
// Look for BOINC Client in list of all running processes
195
retval = procinfo_setup(piv);
196
if (retval) return false; // Should never happen
198
for (unsigned int i=0; i<piv.size(); i++) {
199
PROCINFO& pi = piv[i];
200
if (!strcmp(pi.command, "boinc")) {
204
if (!strcmp(pi.command, "boinc_client")) {
210
wxLogTrace(wxT("Function Status"), wxT("CBOINCClientManager::IsBOINCCoreRunning - Returning '%d'"), (int)running);
211
wxLogTrace(wxT("Function Start/End"), wxT("CBOINCClientManager::IsBOINCCoreRunning - Function End"));
216
bool CBOINCClientManager::StartupBOINCCore() {
217
wxLogTrace(wxT("Function Start/End"), wxT("CMainDocument::StartupBOINCCore - Function Begin"));
219
bool bReturnValue = false;
220
wxString strExecute = wxEmptyString;
222
if (IsBOINCCoreRunning()) return true;
224
#if defined(__WXMSW__)
225
LPTSTR szExecute = NULL;
226
LPTSTR szDataDirectory = NULL;
228
if (IsBOINCConfiguredAsDaemon()) {
229
start_daemon_via_daemonctrl();
231
m_bBOINCStartedByManager = true;
232
bReturnValue = IsBOINCCoreRunning();
235
// Append boinc.exe to the end of the strExecute string and get ready to rock
237
wxT("\"%s\\boinc.exe\" --redirectio --launched_by_manager %s"),
238
wxGetApp().GetRootDirectory().c_str(),
239
wxGetApp().GetArguments().c_str()
242
PROCESS_INFORMATION pi;
244
BOOL bProcessStarted;
246
memset(&pi, 0, sizeof(pi));
247
memset(&si, 0, sizeof(si));
250
si.dwFlags = STARTF_USESHOWWINDOW;
251
si.wShowWindow = SW_HIDE;
253
szExecute = (LPTSTR)strExecute.c_str();
254
if (wxGetApp().GetDataDirectory().empty()) {
255
szDataDirectory = NULL;
257
szDataDirectory = (LPTSTR)wxGetApp().GetDataDirectory().c_str();
260
wxLogTrace(wxT("Function Status"), wxT("CMainDocument::StartupBOINCCore - szExecute '%s'\n"), szExecute);
261
wxLogTrace(wxT("Function Status"), wxT("CMainDocument::StartupBOINCCore - szDataDirectory '%s'\n"), szDataDirectory);
263
bProcessStarted = CreateProcess(
269
CREATE_NEW_PROCESS_GROUP|CREATE_NO_WINDOW,
276
if (bProcessStarted) {
277
m_lBOINCCoreProcessId = pi.dwProcessId;
278
m_hBOINCCoreProcess = pi.hProcess;
282
#elif defined(__WXMAC__)
284
#if 0 // The Mac version of wxExecute(wxString& ...) crashes if there is a space in the path
291
ProcessSerialNumber ourPSN;
295
if (IsBOINCConfiguredAsDaemon() == NewStyleDaemon) {
296
system ("launchctl load /Library/LaunchDaemons/edu.berkeley.boinc.plist");
297
system ("launchctl start edu.berkeley.boinc");
298
bReturnValue = IsBOINCCoreRunning();
301
// Get the full path to core client inside this application's bundle
302
err = GetCurrentProcess (&ourPSN);
304
err = GetProcessBundleLocation(&ourPSN, &ourFSRef);
307
err = FSRefMakePath (&ourFSRef, (UInt8*)buf, sizeof(buf));
310
#if 0 // The Mac version of wxExecute(wxString& ...) crashes if there is a space in the path
311
strExecute = wxT("\"");
312
strExecute += wxT(buf);
313
strExecute += wxT("/Contents/Resources/boinc\" --redirectio --launched_by_manager");
314
m_lBOINCCoreProcessId = ::wxExecute(strExecute);
315
#else // Use wxExecute(wxChar **argv ...) instead of wxExecute(wxString& ...)
316
strcat(buf, "/Contents/Resources/boinc");
318
argv[1] = "--redirectio";
319
argv[2] = "--launched_by_manager";
322
if (!g_use_sandbox) {
323
argv[3] = "--insecure";
327
// Under wxMac-2.8.0, wxExecute starts a separate thread
328
// to wait for child's termination.
329
// That wxProcessTerminationThread uses a huge amount of processor
330
// time (about 11% of one CPU on 2GHz Intel Dual-Core Mac).
331
// m_lBOINCCoreProcessId = ::wxExecute(argv);
333
"/Library/Application Support/BOINC Data",
334
buf, argv[3] ? 4 : 3, argv, 0.0, m_lBOINCCoreProcessId
342
#else // Unix based systems
343
wxString savedWD = ::wxGetCwd();
345
wxSetWorkingDirectory(wxGetApp().GetDataDirectory());
347
// Append boinc.exe to the end of the strExecute string and get ready to rock
348
strExecute = wxGetApp().GetRootDirectory() + wxT("boinc --redirectio --launched_by_manager");
350
if (!g_use_sandbox) {
351
strExecute += wxT(" --insecure");
355
wxLogTrace(wxT("Function Status"), wxT("CMainDocument::StartupBOINCCore - szExecute '%s'\n"), strExecute.c_str());
356
wxLogTrace(wxT("Function Status"), wxT("CMainDocument::StartupBOINCCore - szDataDirectory '%s'\n"), wxGetApp().GetDataDirectory().c_str());
358
m_lBOINCCoreProcessId = ::wxExecute(strExecute);
360
wxSetWorkingDirectory(savedWD);
363
if (0 != m_lBOINCCoreProcessId) {
364
m_bBOINCStartedByManager = true;
366
// Allow time for daemon to start up so we don't keep relaunching it
367
for (int i=0; i<100; i++) { // Wait up to 1 seccond in 10 ms increments
369
if (IsBOINCCoreRunning()) break;
373
wxLogTrace(wxT("Function Start/End"), wxT("CMainDocument::StartupBOINCCore - Function End"));
379
static tstring downcase_string(tstring& orig) {
380
tstring retval = orig;
381
for (size_t i=0; i < retval.length(); i++) {
382
retval[i] = tolower(retval[i]);
388
void CBOINCClientManager::KillClient() {
389
ULONG cbBuffer = 128*1024; // 128k initial buffer
390
PVOID pBuffer = NULL;
391
PSYSTEM_PROCESSES pProcesses = NULL;
393
if (m_hBOINCCoreProcess != NULL) {
394
kill_program(m_hBOINCCoreProcess);
398
// Get a snapshot of the process and thread information.
399
diagnostics_get_process_information(&pBuffer, &cbBuffer);
401
// Lets start walking the structures to find the good stuff.
402
pProcesses = (PSYSTEM_PROCESSES)pBuffer;
404
if (pProcesses->ProcessId) {
405
tstring strProcessName = pProcesses->ProcessName.Buffer;
406
if (downcase_string(strProcessName) == tstring(_T("boinc.exe"))) {
407
TerminateProcessById(pProcesses->ProcessId);
412
// Move to the next structure if one exists
413
if (!pProcesses->NextEntryDelta) {
416
pProcesses = (PSYSTEM_PROCESSES)(((LPBYTE)pProcesses) + pProcesses->NextEntryDelta);
417
} while (pProcesses);
420
if (pBuffer) HeapFree(GetProcessHeap(), NULL, pBuffer);
425
void CBOINCClientManager::KillClient() {
426
std::vector<PROCINFO> piv;
429
if (m_lBOINCCoreProcessId) {
430
kill_program(m_lBOINCCoreProcessId);
434
retval = procinfo_setup(piv);
435
if (retval) return; // Should never happen
437
for (unsigned int i=0; i<piv.size(); i++) {
438
PROCINFO& pi = piv[i];
439
if (!strcmp(pi.command, "boinc")) {
448
void CBOINCClientManager::ShutdownBOINCCore() {
449
wxLogTrace(wxT("Function Start/End"), wxT("CBOINCClientManager::ShutdownBOINCCore - Function Begin"));
451
CMainDocument* pDoc = wxGetApp().GetDocument();
453
bool bClientQuit = false;
454
wxString strConnectedCompter = wxEmptyString;
455
wxString strPassword = wxEmptyString;
458
wxASSERT(wxDynamicCast(pDoc, CMainDocument));
461
// Mac Manager shuts down client only if Manager started client
462
if (!m_bBOINCStartedByManager) return;
466
if (IsBOINCConfiguredAsDaemon()) {
467
stop_daemon_via_daemonctrl();
472
pDoc->GetConnectedComputerName(strConnectedCompter);
473
if (!pDoc->IsComputerNameLocal(strConnectedCompter)) {
475
if (!rpc.init("localhost")) {
476
pDoc->m_pNetworkConnection->GetLocalPassword(strPassword);
477
rpc.authorize((const char*)strPassword.mb_str());
478
if (IsBOINCCoreRunning()) {
480
for (iCount = 0; iCount <= 10; iCount++) {
481
if (!bClientQuit && !IsBOINCCoreRunning()) {
482
wxLogTrace(wxT("Function Status"), wxT("CBOINCClientManager::ShutdownBOINCCore - (localhost) Application Exit Detected"));
486
wxLogTrace(wxT("Function Status"), wxT("CBOINCClientManager::ShutdownBOINCCore - (localhost) Application Exit NOT Detected, Sleeping..."));
495
if (IsBOINCCoreRunning()) {
496
pDoc->CoreClientQuit();
497
for (iCount = 0; iCount <= 10; iCount++) {
498
if (!bClientQuit && !IsBOINCCoreRunning()) {
499
wxLogTrace(wxT("Function Status"), wxT("CBOINCClientManager::ShutdownBOINCCore - Application Exit Detected"));
503
wxLogTrace(wxT("Function Status"), wxT("CBOINCClientManager::ShutdownBOINCCore - Application Exit NOT Detected, Sleeping..."));
515
m_lBOINCCoreProcessId = 0;
517
wxLogTrace(wxT("Function Start/End"), wxT("CBOINCClientManager::ShutdownBOINCCore - Function End"));
521
BEGIN_EVENT_TABLE(ClientCrashDlg, wxDialog)
522
EVT_BUTTON(wxID_HELP, ClientCrashDlg::OnHelp)
525
IMPLEMENT_CLASS(ClientCrashDlg, wxDialog)
527
ClientCrashDlg::ClientCrashDlg(double timeDiff) : wxDialog( NULL, wxID_ANY, wxT(""), wxDefaultPosition ) {
528
wxString strDialogTitle = wxEmptyString;
529
wxString strDialogMessage = wxEmptyString;
530
int minutes = wxMax((int)((timeDiff + 59.) / 60.), 2);
531
CSkinAdvanced* pSkinAdvanced = wxGetApp().GetSkinManager()->GetAdvanced();
532
wxASSERT(pSkinAdvanced);
534
// %s is the application name
535
// i.e. 'BOINC Manager', 'GridRepublic Manager'
536
strDialogTitle.Printf(
537
_("%s - Unexpected Exit"),
538
pSkinAdvanced->GetApplicationName().c_str()
540
SetTitle(strDialogTitle.c_str());
542
// 1st %s is the application name
543
// i.e. 'BOINC Manager', 'GridRepublic Manager'
544
// 2st %s is the project name
545
// i.e. 'BOINC', 'GridRepublic'
546
strDialogMessage.Printf(
547
_("The %s client has exited unexpectedly 3 times within the last %d minutes.\nWould you like to restart it again?"),
548
pSkinAdvanced->GetApplicationShortName().c_str(),
552
wxBoxSizer *topsizer = new wxBoxSizer( wxVERTICAL );
553
wxBoxSizer *icon_text = new wxBoxSizer( wxHORIZONTAL );
555
icon_text->Add( CreateTextSizer( strDialogMessage ), 0, wxALIGN_CENTER | wxLEFT, 10 );
556
topsizer->Add( icon_text, 1, wxCENTER | wxLEFT|wxRIGHT|wxTOP, 10 );
558
wxStdDialogButtonSizer *sizerBtn = CreateStdDialogButtonSizer(wxYES | wxNO | wxHELP);
559
SetEscapeId(wxID_NO); // Changes return value of NO button to wxID_CANCEL
562
topsizer->Add(sizerBtn, 0, wxEXPAND | wxALL, 10 );
564
SetAutoLayout( true );
565
SetSizer( topsizer );
567
topsizer->SetSizeHints( this );
568
topsizer->Fit( this );
569
wxSize size( GetSize() );
570
if (size.x < size.y*3/2)
576
Centre( wxBOTH | wxCENTER_FRAME);
580
void ClientCrashDlg::OnHelp(wxCommandEvent& WXUNUSED(eventUnused)) {
581
wxString strURL = wxGetApp().GetSkinManager()->GetAdvanced()->GetOrganizationHelpUrl();
585
wxT("%s?target=crash_detection&version=%s&controlid=%d"),
587
wxString(BOINC_VERSION_STRING, wxConvUTF8).c_str(),
590
wxLaunchDefaultBrowser(wxurl);