client: Fix idle detection for Apple Remote Desktop and screen sharing under Mac OS 10.7

svn path=/trunk/boinc/; revision=25018
This commit is contained in:
Charlie Fenton 2012-01-10 10:37:37 +00:00
parent dd16170fc1
commit 5ef74674e8
2 changed files with 53 additions and 25 deletions

View File

@ -346,3 +346,11 @@ David 9 Jan 2012
feeder.cpp feeder.cpp
sched_version.cpp sched_version.cpp
hr_info.cpp,h hr_info.cpp,h
Charlie 10 Jan 2012
- client: Fix idle detection for Apple Remote Desktop and screen sharing
(VNC) under Mac OS 10.7. See comments in HOST_INFO::users_idle() for
details.
client/
hostinfo_unix.cpp

View File

@ -1584,14 +1584,24 @@ inline bool user_idle(time_t t, struct utmp* u) {
// daemon running as user boinc_master, this API works properly under OS 10.6 // daemon running as user boinc_master, this API works properly under OS 10.6
// but fails under OS 10.5 and earlier. // but fails under OS 10.5 and earlier.
// //
// In OS 10.7, IOHIDGetParameter() fails to recognize activity from remote
// logins via Apple Remote Desktop or Screen Sharing (VNC), but the
// CGEventSourceSecondsSinceLastEventType() API does work with ARD and VNC,
// and CGEventSourceSecondsSinceLastEventType() does work even when BOINC
// is a pre-login launchd daemon running as user boinc_master, provided that
// it is not called too soon after system restart.
//
// So we use weak-linking of NxIdleTime() to prevent a run-time crash from the // So we use weak-linking of NxIdleTime() to prevent a run-time crash from the
// dynamic linker, and use the IOHIDGetParameter() API if NXIdleTime does not // dynamic linker and use it if it exists.
// exist. // If NXIdleTime does not exist, use CGEventSourceSecondsSinceLastEventType()
// under OS 10.7, or IOHIDGetParameter() under OS 10.6.
// //
bool HOST_INFO::users_idle( bool HOST_INFO::users_idle(
bool check_all_logins, double idle_time_to_run, double *actual_idle_time bool check_all_logins, double idle_time_to_run, double *actual_idle_time
) { ) {
static bool error_posted = false; static bool error_posted = false;
static long OSVersionInfo = 0;
OSStatus err = noErr;
double idleTime = 0; double idleTime = 0;
io_service_t service; io_service_t service;
kern_return_t kernResult = kIOReturnError; kern_return_t kernResult = kIOReturnError;
@ -1605,6 +1615,9 @@ bool HOST_INFO::users_idle(
if (!triedToLoadNXIdleTime) { if (!triedToLoadNXIdleTime) {
triedToLoadNXIdleTime = true; triedToLoadNXIdleTime = true;
err = Gestalt(gestaltSystemVersion, &OSVersionInfo);
if (err) OSVersionInfo = 0;
IOKitlib = dlopen ("/System/Library/Frameworks/IOKit.framework/IOKit", RTLD_NOW ); IOKitlib = dlopen ("/System/Library/Frameworks/IOKit.framework/IOKit", RTLD_NOW );
if (IOKitlib) { if (IOKitlib) {
myNxIdleTimeProc = (nxIdleTimeProc)dlsym(IOKitlib, "NXIdleTime"); myNxIdleTimeProc = (nxIdleTimeProc)dlsym(IOKitlib, "NXIdleTime");
@ -1631,6 +1644,12 @@ bool HOST_INFO::users_idle(
} }
} }
} else { // NXIdleTime API does not exist in OS 10.6 and later } else { // NXIdleTime API does not exist in OS 10.6 and later
if (OSVersionInfo >= 0x1070) {
if (TickCount() > (120*60)) { // If system has been up for more than 2 minutes
idleTime = CGEventSourceSecondsSinceLastEventType
(kCGEventSourceStateCombinedSessionState, kCGAnyInputEventType);
}
} else { // OS Version < 10.7
if (gEventHandle) { if (gEventHandle) {
kernResult = IOHIDGetParameter( gEventHandle, CFSTR(EVSIOIDLE), sizeof(UInt64), &params, &rcnt ); kernResult = IOHIDGetParameter( gEventHandle, CFSTR(EVSIOIDLE), sizeof(UInt64), &params, &rcnt );
if ( kernResult != kIOReturnSuccess ) { if ( kernResult != kIOReturnSuccess ) {
@ -1656,7 +1675,8 @@ bool HOST_INFO::users_idle(
goto bail; goto bail;
} }
} }
} // End gEventHandle == NULL } // End (gEventHandle == NULL)
} // End (OSVersionInfo < 0x1070)
} // End NXIdleTime API does not exist } // End NXIdleTime API does not exist
bail: bail: