diff --git a/checkin_notes b/checkin_notes index 4e3c0b9dcf..69199e9ed4 100755 --- a/checkin_notes +++ b/checkin_notes @@ -2087,3 +2087,21 @@ Bruce 27 Feb 2007 sched/ server_types.C +Charlie 28 Feb 2007 + Mac: The Mac screensaver launches the core client if not already running. + In this case, it used to kill the cc when screensaver was dismissed. + But Mac OS X dismisses screensavers when energy saver puts displays + to sleep, so we want cc to then continue running. New code launches + cc with -saver flag, lets cc run when saver quits. New logic in cc + quits if (launched by screensaver) and (recent user activity) and + (parent [screensaver] has exited). This takes into account that if + user invoked screensaver by moving mouse into "hot corner" there will + be recent user activity. Added logic to screensaver to relaunch cc in + case of certain race conditions (e.g., screensaver started, dismissed, + restarted in rapid succession.) + + client/ + cs_prefs.C + clientgui/ + mac/ + mac_saver_module.cpp diff --git a/client/cs_prefs.C b/client/cs_prefs.C index 3ebd6d5974..3a181f4f1f 100644 --- a/client/cs_prefs.C +++ b/client/cs_prefs.C @@ -129,7 +129,9 @@ inline bool now_between_two_hours(int start_hour, int end_hour) { // void CLIENT_STATE::check_suspend_activities(int& reason) { reason = 0; - +#ifdef __APPLE__ + double idletime; +#endif // Don't work while we're running CPU benchmarks // if (are_cpu_benchmarks_running()) { @@ -140,11 +142,25 @@ void CLIENT_STATE::check_suspend_activities(int& reason) { bool old_user_active = user_active; user_active = !host_info.users_idle( check_all_logins, global_prefs.idle_time_to_run +#ifdef __APPLE__ + , &idletime +#endif ); if (user_active != old_user_active) { request_schedule_cpus("Idle state change"); } +#ifdef __APPLE__ + // Mac screensaver launches client if not already running. OS X + // quits screensaver when energy saver puts display to sleep, but + // we want to keep crunching. Also, user can start Mac screensaver + // by putting cursor in "hot corner" so idletime may be very small + // initially. If screensaver started client, this code tells client + // to exit when user becomes active, accounting for all these factors. + if (started_by_screensaver && (idletime < 30) && + (getppid() == 1) ) // true if parent has exited + gstate.requested_exit = true; +#endif switch(run_mode.get_current()) { case RUN_MODE_ALWAYS: break; diff --git a/clientgui/mac/mac_saver_module.cpp b/clientgui/mac/mac_saver_module.cpp index dd82549220..2c72aed8eb 100755 --- a/clientgui/mac/mac_saver_module.cpp +++ b/clientgui/mac/mac_saver_module.cpp @@ -145,7 +145,7 @@ const char * BOINCNoProjectsDetectedMsg = "BOINC is not attached to any project const char * BOINCNoGraphicAppsExecutingMsg = "Project does not support screensaver graphics: "; const char * BOINCNoGraphicsSupportedMsg = "This BOINC installation does not support screensaver graphics: "; const char * BOINCUnrecoverableErrorMsg = "Sorry, an unrecoverable error occurred"; -const char * BOINCTestmodeMg = "This BOINC screensaver does not support Test mode"; +const char * BOINCTestmodeMg = "BOINC screensaver is running, but cannot display graphics in test mode."; //const char * BOINCExitedSaverMode = "BOINC is no longer in screensaver mode."; @@ -216,7 +216,8 @@ OSStatus initBOINCApp() { pid_t myPid; int status; OSStatus err; - + static int retryCount = 0; + saverState = SaverState_CantLaunchCoreClient; CoreClientPID = FindProcessPID("boinc", 0); @@ -226,6 +227,11 @@ OSStatus initBOINCApp() { return noErr; } + wasAlreadyRunning = false; + + if (++retryCount > 3) + return -1; + err = GetpathToBOINCManagerApp(boincPath, sizeof(boincPath)); if (err) { // If we couldn't find BOINCManager.app, try default path strcpy(boincPath, "/Applications/"); @@ -257,7 +263,7 @@ OSStatus initBOINCApp() { _exit(status); } - status = execl(boincPath, boincPath, "-redirectio", (char *) 0); + status = execl(boincPath, boincPath, "-redirectio", "-saver", (char *) 0); fflush(NULL); _exit(127); // execl error (execl should never return) } else { @@ -430,17 +436,21 @@ void closeBOINCSaver() { setBannerText(0, NULL); - // Kill core client if we launched it if (!wasAlreadyRunning) +#if 0 // OS X quits screensaver when energy saver puts display to + // sleep, but we want to keep crunching. So don't kill it. + // Code in core client now quits on user activity if screen + // saver launched it (2/28/07). if (CoreClientPID) { - kill(CoreClientPID, SIGTERM); + kill(CoreClientPID, SIGTERM); // Kill core client if we launched it } - CoreClientPID = 0; - gQuitCounter = 0; - wasAlreadyRunning = false; - gQuitRPCThread = false; - saverState = SaverState_Idle; +#endif + CoreClientPID = 0; + gQuitCounter = 0; + wasAlreadyRunning = false; + gQuitRPCThread = false; + saverState = SaverState_Idle; } @@ -480,9 +490,10 @@ OSStatus RPCThread(void* param) { if (val == noErr) break; - // Attempt to reinitialize the RPC client and state + // Attempt to restart BOINC Client if needed, reinitialize the RPC client and state rpc->close(); - rpc->init(NULL); + initBOINCApp(); + MPExit(noErr); // Exit the thread // Error message after timeout? } @@ -499,9 +510,10 @@ OSStatus RPCThread(void* param) { val = rpc->get_screensaver_mode(gClientSaverStatus); if (val) { - // Attempt to reinitialize the RPC client and state + // Attempt to restart BOINC Client if needed, reinitialize the RPC client and state rpc->close(); - rpc->init(NULL); + initBOINCApp(); + MPExit(noErr); // Exit the thread // Error message after timeout? } @@ -550,8 +562,10 @@ OSStatus RPCThread(void* param) { } // end for() loop gStatusMessageUpdated = true; } else { // rpc call returned error + // Attempt to restart BOINC Client if needed, reinitialize the RPC client and state rpc->close(); - rpc->init(NULL); + initBOINCApp(); + MPExit(noErr); // Exit the thread } // end if (rpc.get_results(results) {} else {} } // end if (! gStatusMessageUpdated)