Skip to content

[Awake] SetThreadExecutionState failure not handled - silent failure bug when changing state #41674

@daverayment

Description

@daverayment

Microsoft PowerToys version

0.94

Installation method

Dev build in Visual Studio

Area(s) with issue?

Awake

Steps to reproduce

Description

Awake currently ignores failures from the SetThreadExecutionState Win32 API call, which lies at the core of its functionality. If such a failure happens, the UI will show that keep-awake is active, but the user's system may still go to sleep because the state wasn't applied.

Root cause

In Manager.cs, the monitor thread calls SetAwakeState() but ignores its return value:

    while (true)
    {
        ExecutionState state = _stateQueue.Take();

        Logger.LogInfo($"Setting state to {state}");

        SetAwakeState(state);
    }

SetAwakeState() actually correctly detects failures and returns false when SetThreadExecutionState returns NULL (0), but this failure is never acted upon or logged.

Impact

  • Users will see Awake as active in the system tray, but their computer could still go to sleep.
  • Users will be unaware of the reason why the keep-awake functionality has failed.
  • Users will not be able to rely on the application to support their chosen tasks, e.g. keeping the system awake while they execute a long-running unattended piece of work.

Why can SetThreadExecutionState fail?

  • When called from Windows services. (I'm unsure whether this applies for Awake).
  • When called with invalid parameters. (Not an issue with Awake).
  • When resources are constrained.
  • If there are insufficient process privileges.
  • If conflicting power management options are applied, e.g. by an OEM's power management software.
  • Hardware/driver issues.

Proposed solution

At the very least, this should be logged and Awake should set its status back to Passive mode, indicating the failure:

while (true)
{
    ExecutionState state = _stateQueue.Take();
    Logger.LogInfo($"Setting state to {state}");
    
    if (!SetAwakeState(state))
    {
        Logger.LogError($"Failed to set execution state to {state}");
        
        // Revert to passive mode
        CurrentOperatingMode = AwakeMode.PASSIVE;
        SetModeShellIcon();
    }
}

Other possibilities:

  • Show an error icon in the systray.
  • Track failure occurrence via telemetry.
  • Implement retry logic via exponential back-off in case it is a temporary issue.
  • Show to the user that there's been an error via other means, e.g. a dialog box.

Severity and priority

I suggest:

  • High priority: The nature of the silent failure undermines the core functionality of the application.
  • Moderate severity: It does not cause a crash.

✔️ Expected Behavior

If Awake fails to apply the chosen keep-awake state, the error should be reported back to the user and logged.

❌ Actual Behavior

Awake will always act as though the state was successfully applied.

Additional Information

No response

Other Software

No response

Metadata

Metadata

Assignees

Labels

Issue-BugSomething isn't workingProduct-AwakeIssues regarding the PowerToys Awake utilityResolution-Fix CommittedFix is checked in, but it might be 3-4 weeks until a release.

Type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions