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 (Cocoa-dev@lists.apple.com)

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:
http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Reply via email to