The last few years I have wasted my share of hours to understand how Mac OSX various sleep states work. My main challenge has been that I encrypt the harddrive, and from a security point of view, that doesn’t help much if you have the computer in sleep mode with the key in memory (however, you don’t need to use FileVault disk encryption to find these notes helpful).
First of all, it’s important to know that this post covers modern MacBook Pros and the likes. See here for more info from Apple. Other Macs may be similar, but they probably don’t have the Safe Sleep option.
Disclaimer: The understanding of how things work may be wrong, but this is the best understanding I have been able to develop based on Apple support notes, various resources on the Internet, and my own testing.
It took some time before I realised that what I didn’t understand was that there are actually four different sleep modes on Macs, and the various settings controlled with pmset actually result in different behaviour depending on the hibernatemode setting. It seems that most of the posts and threads on the Internet covering this topic have the same confusion, more or less. Once I understood that, it was just a matter of trial and error.
Four Modes of Sleep…
Ok, so to the four modes:
- Sleep or memory sleep: This is what happens when you close the lid or let the computer idle for some time. Power to display, disk, and other systems is turned off
- Standby or Safe Sleep: Memory state is written to disk and after a certain period memory power is turned off (standard 3 hours)
- Auto poweroff or EU standby: When on AC power, standard sleep is not enabled, but the Mac can switch into a standby mode with state in memory, but where memory state is not written to disk (Apple claims that this is a hibernation state, but that is not my experience)
- Hibernation: All power is off, all state has been written to a disk image. You know this has happened when you get the Mac icon, then see a progress bar consisting of think white lines while it is loading state from disk
The standard Macbook Pro scheme (hibernatemode=3) is the so-called Safe Sleep. Memory is written to disk after 3 hours (default), when battery is low, the memory power is turned off, and the Mac is then in hibernation mode. That is why it was called Safe Sleep. When it was introduced, it would write to disk and then keep state in memory until battery was low. This behaviour seems to still be the default (as described here).
How to Control Sleep
Here it is useful to learn about the pmset command. It needs to be run as sudo pmset or as the root user. The two basic commands that are useful are: sudo pmset -g custom and sudo pmset -g log. The first will list out all the settings for both battery and AC, while the other will show you the power and sleep state log.
If you want to change how long time it takes to move from standby into hibernation when you use Safe Sleep, you can do sudo pmset -a standbydelay 1800 to make your computer go into hibernation after 1800 seconds, i.e. 30 minutes. The confusing thing here is that the setting is not called hibernationdelay.
Another important thing to know is that there is a long list of events that can make your Mac wake up from standby: you enter your house and the Wifi network is available, you plug in AC, standbydelay timer is triggered and more. And there are also a number of things that can prevent a standby: USB connected drives, Bluetooth connections, addressbook sync process, remote connections (terminals), and so on. This article from Apple covers some of the other situations where sleep and wake may be affected.
If you don’t use Filevault encryption, you are ok with the standard settings, unless you want to prevent your computer from waking up all the time. There are also histories of bugs in wireless routers and other issues that keep waking up the Mac, draining it for battery. See below for more information about the unsecure-sleep.sh script.
If you do use Filevault, there is a setting called destroyfvkeyonstandby which basically throws the Filevault key out of memory. The confusing part of this setting is that what standby actually is, is dependent on the hibernatemode setting. More about that later.
SMC and NVRAM reset
One important thing when you mess around with these settings: BIOS memory settings (SMC and NVRAM) have settings that are related, so for some settings, your computer will crash unless you reset these BIOS settings. Here is how I do it:
- SMC reset first, then NVRAM.
- Shut down your Mac.
- Unplug the MagSafe or USB-C power adapter from your computer for Macs with removable battery and plug IN power adapter for Macs without removable battery.
- Using the built-in keyboard, press Shift-Control-Option on the left side of the keyboard, then press and hold the power button at the same time. Hold these keys and the power button for 10 seconds. You will not see or hear anything (if you have a 2016 MacBook Pro with Touch ID, the Touch ID button is also the power button).
- Release all keys. You still don’t really know if anything happened.
- Press the power button again to turn on your Mac and immediately hold down these four keys together: Option, Command, P, and R. Keep holding the keys for about 20 seconds, during which your Mac might appear to restart (the screen will flash).
- When it starts up again, you will notice that the screen has max brightness (if you have a Mac that plays a startup sound when you turn it on, you can release the keys after the second startup sound).
If you don’t do these resets, the computer may not respond to the settings changes the way you expect them to. This adds to the difficulties in trying to figure out what is going on.
The hibernatemode=25 Setting
Ok, time to look at the hibernatemode setting. For laptops, there are only two interesting values, 3 and 25. 3 is the Safe Sleep/standby mode, while 25 is the go directly to hibernation setting. So, here is the really bad thing: the settings relevant for standby actually still work, but will just mess things up for you; especially if you destroy the Filevault key on standby. There are a few gotches where you will enter standby mode or wake up even with hibernatemode=25, and you will then get a crash because there is no Filevault key available to go into hibernation and after a while, the computer will turn itself off completely (aka crash).
Also, according to the documentation mode 25 should support standbydelay settings, but I have struggled with actually making the sleeptimer hit.
Big thanks to the MacOS security guide work for clarifying some of these issues.
I have a small git repository with the scripts I use. The most secure approach is to force your Mac to go directly to hibernation and throw the key (secure-hibernate.sh). In order to keep things working, you then have to remember that sleep = standby = hibernation, but not consistently in the settings. Importantly, the sleep setting will control how long the computer will be idle before hibernating. But even more important, standby and standbydelay must be set to 0 to ensure that you don’t get into standby instead of hibernation! Finally, to avoid that you get wake ups at the wrong times, you should turn off all the dark wakes. This is basically what secure-hibernate.sh does for you.
You can use the check-wake-ups.sh script to get a log of all wakeups.
2017-08-13 12:45:44 +0200 Wake Wake from Hibernate [CDNVA] due to EC.LidOpen/Lid Open: Using BATT (Charge:44%) 60 secs 2017-08-13 15:33:57 +0200 Wake Wake from Standby [CDNVA] due to EC.DarkPME EC.ACDetach/Lid Open: Using BATT (Charge:100%) 1406 secs 2017-08-13 16:00:47 +0200 Wake Wake from Hibernate [CDNVA] due to EC.LidOpen/Lid Open: Using BATT (Charge:100%) 134 secs 2017-08-13 16:04:40 +0200 Wake Wake from Hibernate [CDNVA] due to EC.LidOpen/Lid Open: Using BATT (Charge:99%) 2265 secs 2017-08-13 16:50:51 +0200 Wake Wake from Hibernate [CDNVA] due to EC.LidOpen/Lid Open: Using BATT (Charge:91%) 686 secs 2017-08-13 19:00:25 +0200 Wake Wake from Hibernate [CDNVA] due to EC.LidOpen/Lid Open: Using BATT (Charge:87%) 2365 secs 2017-08-14 05:52:51 +0200 Wake Wake from Hibernate [CDNVA] due to EC.LidOpen/Lid Open: Using BATT (Charge:100%)
There is still a gotcha here. If you connect your computer to AC when it is hibernating, it should stay hibernated. However, if you are connected to AC, the autopoweroff setting takes precedence over the sleep setting. This setting basically puts your computer in standby (see the log above for an example), even when hibernatemode=25! I have not found a way to hibernate the computer automatically when on AC, so you should use the sleep option in the system menu when you are on AC (note that the behaviour I have observed is contrary to Apple’s public information that claims that the autopoweroff mode is a hibernation mode).
Another update, Sep 2 2017: My habits changed a bit, and I found that there is an issue with some MacBook Pro’s (all?) where acwake is ignored and the Mac wakes up when you plug it into AC (you will see EC.ACAttach using check-wake-ups.sh). I have found no way to fix that yet.
A More Pragmatic Approach
It is very tempting to try to get the best of both worlds: both sleep to memory for a while, then throw the key and hibernate to disk. The logical way of doing this is to combine standbydelay with hibernatemode 3 and destroyfvkeyonstandby. THIS WILL NOT WORK!!!! Don’t waste your time. The reason is that there is no setting to keep the key while sleeping to memory and hibernating, the key is thrown away the moment it goes into sleep and will cause your Mac to crash. This is what tricked me up for a while because it will work some times and quite often if you turn off the dark wakes. I have kept this script in the repo for reference: secure-sleep.sh.
The best approach here is to use hibernatemode=3 and NOT throw the key. This is basically Apple’s standard mode. The issue however is that since memory is not powered down intil battery is low, you are potentially exposed to hackers extracting the encryption key from memory for potentially a long time. This is what unsecure-sleep.sh does. It is indeed the best approach if you are not worried about security, but just want to prevent your Mac from waking up and want to save as much battery as possible.
It also worth noting that unsecure-sleep.sh (and secure-hibernate.sh) turns off all dark wakes, so you get rid of all the “stuff” going on while your Mac is asleep (as described here by Apple)
I’m happy to get feedback on this to identity any issues or improvements!