Description
When -u (UserActive / ES_USER_PRESENT) is included in any flag combination, SetThreadExecutionState returns 0 (failure) and no assertions are set at all. The system sleeps as if caffeinate was never started.
This affects both bundled (caffeinate -disu) and individual (caffeinate -d -i -s -u) flag usage.
Expected behavior
caffeinate -d -i -s -u should prevent the system and display from sleeping.
Actual behavior
SetThreadExecutionState returns 0 (NULL = failure). No sleep prevention is active. System goes to sleep normally.
Root cause
ES_USER_PRESENT (0x00000004) is deprecated on modern Windows. From the Win32 docs:
ES_USER_PRESENT - This value is not supported.
When combined with other flags, the entire call fails and none of the requested states are set.
The return value was discarded ($null = ...), so the failure was completely silent.
Verified behavior
| Flags |
Return |
ES_CONTINUOUS |
OK |
ES_CONTINUOUS | ES_SYSTEM_REQUIRED |
OK |
ES_CONTINUOUS | ES_DISPLAY_REQUIRED |
OK |
ES_CONTINUOUS | ES_SYSTEM_REQUIRED | ES_DISPLAY_REQUIRED |
OK |
ES_CONTINUOUS | ES_USER_PRESENT |
0 (FAIL) |
ES_CONTINUOUS | ES_SYSTEM_REQUIRED | ES_DISPLAY_REQUIRED | ES_USER_PRESENT |
0 (FAIL) |
ES_USER_PRESENT alone |
0 (FAIL) |
Fix
- Never pass
ES_USER_PRESENT to the API
- When
-u is requested, substitute ES_DISPLAY_REQUIRED | ES_SYSTEM_REQUIRED
- Check the return value of
SetThreadExecutionState and warn on failure
- Re-assert execution state every 30s as a safety net
Description
When
-u(UserActive /ES_USER_PRESENT) is included in any flag combination,SetThreadExecutionStatereturns 0 (failure) and no assertions are set at all. The system sleeps as if caffeinate was never started.This affects both bundled (
caffeinate -disu) and individual (caffeinate -d -i -s -u) flag usage.Expected behavior
caffeinate -d -i -s -ushould prevent the system and display from sleeping.Actual behavior
SetThreadExecutionStatereturns 0 (NULL = failure). No sleep prevention is active. System goes to sleep normally.Root cause
ES_USER_PRESENT(0x00000004) is deprecated on modern Windows. From the Win32 docs:When combined with other flags, the entire call fails and none of the requested states are set.
The return value was discarded (
$null = ...), so the failure was completely silent.Verified behavior
ES_CONTINUOUSES_CONTINUOUS | ES_SYSTEM_REQUIREDES_CONTINUOUS | ES_DISPLAY_REQUIREDES_CONTINUOUS | ES_SYSTEM_REQUIRED | ES_DISPLAY_REQUIREDES_CONTINUOUS | ES_USER_PRESENTES_CONTINUOUS | ES_SYSTEM_REQUIRED | ES_DISPLAY_REQUIRED | ES_USER_PRESENTES_USER_PRESENTaloneFix
ES_USER_PRESENTto the API-uis requested, substituteES_DISPLAY_REQUIRED | ES_SYSTEM_REQUIREDSetThreadExecutionStateand warn on failure