Commit 2a18a8ab authored by Charlie Fenton's avatar Charlie Fenton

client: Revise Apple idle time detection for compatibility with OS 10.6

svn path=/trunk/boinc/; revision=17432
parent 66ec8894
......@@ -2506,3 +2506,11 @@ David 2 Mar 2009
sched/
sched_config.cpp,h
sched_locality.cpp
Charlie 2 Mar 2009
- client: Revise Apple idle time detection for compatibility with OS 10.6.
client/
hostinfo_unix.cpp
lib/
hostinfo.h
......@@ -125,7 +125,8 @@ extern "C" {
} // extern "C"
#endif
NXEventHandle gEventHandle = NULL;
mach_port_t gEventHandle = NULL;
#include "util.h"
#endif // __APPLE__
#ifdef _HPUX_SOURCE
......@@ -1078,20 +1079,86 @@ inline bool user_idle(time_t t, struct utmp* u) {
#ifdef __APPLE__
// NXIdleTime() is an undocumented Apple API to return user idle time, which
// was implemented from before OS 10.0 through OS 10.5. In OS 10.4, Apple
// added the CGEventSourceSecondsSinceLastEventType() API as a replacement for
// NXIdleTime(). However, BOINC could not use this newer API when configured
// as a pre-login launchd daemon unless that daemon was running as root,
// because it could not connect to the Window Server. So BOINC continued to
// use NXIdleTime().
//
// In OS 10.6, Apple removed the NXIdleTime() API. BOINC can instead use the
// IOHIDGetParameter() API in OS 10.6. When BOINC is a pre-login launchd
// daemon running as user boinc_master, this API works properly under OS 10.6
// but fails under OS 10.5 and earlier.
//
// 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
// exist.
//
bool HOST_INFO::users_idle(
bool check_all_logins, double idle_time_to_run, double *actual_idle_time
) {
double idleTime = 0;
if (gEventHandle) {
idleTime = NXIdleTime(gEventHandle);
} else {
// Initialize Mac OS X idle time measurement / idle detection
// Do this here because NXOpenEventStatus() may not be available
// immediately on system startup when running as a deaemon.
gEventHandle = NXOpenEventStatus();
}
static double init_time = 0;
static bool error_posted = false;
double idleTime = 0;
io_service_t service;
kern_return_t kernResult;
UInt64 params;
IOByteCount rcnt = sizeof(UInt64);
if (init_time == 0) init_time = dtime();
if (NXIdleTime) { // Use NXIdleTime API in OS 10.5 and earlier
if (gEventHandle) {
idleTime = NXIdleTime(gEventHandle);
} else {
// Initialize Mac OS X idle time measurement / idle detection
// Do this here because NXOpenEventStatus() may not be available
// immediately on system startup when running as a deaemon.
if ((dtime() - init_time) > 180) { // Limit retries to 180 seconds
msg_printf(NULL, MSG_USER_ERROR,
"User idle detection is disabled: initialization failed."
);
goto bail;
}
gEventHandle = NXOpenEventStatus();
}
} else { // NXIdleTime API does not exist in OS 10.6 and later
if (gEventHandle) {
kernResult = IOHIDGetParameter( gEventHandle, CFSTR(EVSIOIDLE), sizeof(UInt64), &params, &rcnt );
if ( kernResult != kIOReturnSuccess ) {
if (!error_posted) {
msg_printf(NULL, MSG_USER_ERROR,
"User idle time measurement failed because IOHIDGetParameter failed."
);
error_posted = true;
}
goto bail;
}
idleTime = ((double)params) / 1000.0 / 1000.0 / 1000.0;
} else {
// When the system first starts up, allow time for HIDSystem to be available if needed
if ((dtime() - init_time) > 180) { // Limit retries to 180 seconds
msg_printf(NULL, MSG_USER_ERROR,
"Could not connect to HIDSystem: user idle detection is disabled."
);
goto bail;
}
service = IOServiceGetMatchingService(kIOMasterPortDefault, IOServiceMatching(kIOHIDSystemClass));
if (service == 0) goto bail;
kernResult = IOServiceOpen(service, mach_task_self(), kIOHIDParamConnectType, &gEventHandle);
if (kernResult != KERN_SUCCESS) goto bail;
} // End gEventHandle == NULL
} // End NXIdleTime API does not exist
bail:
if (actual_idle_time) {
*actual_idle_time = idleTime;
}
......
......@@ -82,9 +82,16 @@ public:
extern "C" {
#endif
#include <mach/port.h>
#include <IOKit/hidsystem/IOHIDLib.h>
#include <IOKit/hidsystem/IOHIDParameter.h>
// Apple has removed NxIdleTime() beginning with OS 10.6, so we must use
// weak linking to avoid a run-time crash. For details, please see the
// comments in the __APPLE__ version of HOST_INFO::users_idle() in
// client/hostinfo_unix.cpp.
typedef mach_port_t NXEventHandle;
NXEventHandle NXOpenEventStatus(void);
extern double NXIdleTime(NXEventHandle handle);
NXEventHandle NXOpenEventStatus(void) __attribute__((weak_import));
extern double NXIdleTime(NXEventHandle handle) __attribute__((weak_import));
#ifdef __cplusplus
} // extern "C"
#endif
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment