Summary: Scheduled events such as system wake and poweron can be created and canceled programmatically using the IOKit functions IOPMSchedulePowerEvent() and IOPMCancelScheduledPowerEvent(). They can also be created and canceled at the command line using the pmset tool. One of the arguments to IOPMSchedulePowerEvent() and IOPMCancelScheduledPowerEvent() is a CFStringRef identifying the calling app by CFBundleIdentifier. An app's bundle identifier can contain both uppercase and lowercase letters. The bug is that pmset is not able to correctly handle bundle identifiers with uppercase characters. For example, if there is an existing scheduled event from an app with an uppercase bundle id, then pmset is unable to cancel that event. Steps to Reproduce: 1) Download the attached source file "pmsetbug.c" to "~/Downloads" 2) Launch Terminal.app 3) cd Downloads 4) gcc -Wall -framework CoreFoundation -framework IOKit -o pmsetbug pmsetbug.c 5) sudo ./pmsetbug 6) pmset -g sched Scheduled power events: [0] wake at 12/01/09 10:00:00 by com.test.lowercaseapp [1] wake at 12/01/09 11:00:00 by com.test.UppercaseApp 7) sudo pmset schedule cancel wake "12/01/09 10:00:00" "com.test.lowercaseapp" 8) pmset -g sched Scheduled power events: [0] wake at 12/01/09 11:00:00 by com.test.UppercaseApp 9) sudo pmset schedule cancel wake "12/01/09 11:00:00" "com.test.UppercaseApp" Expected Results: The scheduled event is canceled. Actual Results: pmset: Error in scheduling operation Notes: The Darwin source for Mac OS X 10.5.8 is not yet available. However, you can see the bug in the Darwin source for Mac OS X 10.5.7. The problem seems to be in the following source file: http://www.opensource.apple.com/source/PowerManagement/PowerManagement-158.10/pmset/pmset.c At pmset.c:3148-3156 we see this code:
for(i=0; i<argc; i++)
{
// I only speak lower case.
length=strlen(argv[i]);
for(j=0; j<length; j++)
{
argv[i][j] = tolower(argv[i][j]);
}
}
If you remove those lines, then the bug does not occur. We can see why those lines cause a failure in the following source file: http://www.opensource.apple.com/source/IOKitUser/IOKitUser-388.53.11/pwr_mgt.subproj/IOPMAutoWake.c At IOPMAutoWake.c:263-266 there is this conditional:
if( CFEqual(
CFDictionaryGetValue(package, CFSTR(kIOPMPowerEventAppNameKey)),
CFDictionaryGetValue(cancelee, CFSTR(kIOPMPowerEventAppNameKey))
))
If the package and the cancelee differ by case, then the conditional is not true.