Re: Debugging a sleepless Mac
Re: Debugging a sleepless Mac
- Subject: Re: Debugging a sleepless Mac
- From: Michael Nickerson <email@hidden>
- Date: Wed, 16 Mar 2011 15:36:12 -0400
On Mar 16, 2011, at 8:37 AM, Matt Gough wrote:
> I've just been adding code to support NSWorkspaceWillSleepNotification. Having lowered my Computer sleep time right down and left the Mac untouched for several minutes, my code never fires and the Mac doesn't actually go to sleep. Even without my app running and leaving the Mac for several hours I notice that it still won't sleep.
>
> So it seems that something else is preventing idle sleep, but I've no idea how to find the culprit. Is there some defaults setting I can use that will log what the OS wants to do at sleep time and what is blocking it?
>
>
I don't know of a way to log what might be blocking it, but I ran some tests a while back that showed the system has to be idle for 10 minutes before it will sleep. Or, at least the disk has to be idle for 10 minutes, otherwise sleep is deferred. I ran into this with one of my applications that is long running. It (can) access the disk frequently to open and read files. It turned out that was causing my Mac not to sleep - definitely not something I wanted to happen.
What I ended up doing was writing a method that fires via a timer every minute, and checks the sleep time - if I'm within 10 minutes of it, I stop my application from reading anymore. This stopped the problem, so far as my own application was concerned, though as others have pointed out there's plenty of other things that can keep the system from sleeping that you might not have control of.
So, here's a short version of the code I'm using to do this (typed in Mail):
#import <IOKit/pwr_mgt/IOPMLib.h>
#import <IOKit/pwr_mgt/IOPM.h>
- (void)checkIdleTime:(NSTimer *)timer
{
unsigned long mins = 0, systemIdleMinutes = 0;
CFTimeInterval idleSeconds = CGEventSourceSecondsSinceLastEventType( kCGEventSourceStateCombinedSessionState, kCGAnyInputEventType );
static CFTimeInterval lastSeconds = 0.0;
systemIdleMinutes = lrint(idleSeconds / 60.0); /* Gives minutes of inactivity */
if ( lastSeconds > idleSeconds ) {
/* User activity has occurred since last check, if you disabled anything you can re-enable it here. */
}
lastSeconds = idleSeconds;
/* No need to check this if the system isn't idle. */
if ( systemIdleMinutes ) {
mach_port_t master_device_port;
io_connect_t fb = 0;
kern_return_t kr = kIOReturnSuccess;
IOReturn err = kIOReturnSuccess;
kr = IOMasterPort( bootstrap_port, &master_device_port );
if ( kr == kIOReturnSuccess ) {
fb = IOPMFindPowerManagement( master_device_port );
if ( fb ) {
err = IOPMGetAggressiveness( fb, kPMMinutesToSleep, &mins );
if ( (err == kIOReturnSuccess) && (mins > 0) && ((mins - systemIdleMinutes) <= 10) ) {
/* Do whatever you want to notify your app it should stop disk access here */
}
/* If you want to find out how long until the screen dims, you can do the same as above but use kPMMinutesToDim instead. */
IOServiceClose( fb );
}
}
}
}
Do note one limitation of this as is: if the system is set to sleep in 10 minutes or less, it will fire the condition as soon as the timer is hit and there has been no user activity for at least a minute. This is something I've been meaning to look into but haven't as yet.
--------------------------------------
Darkshadow
(aka Michael Nickerson)
http://www.nightproductions.net
_______________________________________________
Cocoa-dev mailing list (email@hidden)
Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden