From 6f18ad7f29d665ab1d3b8963f9a9ec230b93957c Mon Sep 17 00:00:00 2001 From: Anton Potekhin Date: Wed, 26 Apr 2023 17:24:02 +0300 Subject: [PATCH 1/2] Improved prevention from sleep for Win 11 --- server/cmd/preconfig_win.go | 27 ++++++++++++++++++++------- 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/server/cmd/preconfig_win.go b/server/cmd/preconfig_win.go index d36c65a..2de0405 100644 --- a/server/cmd/preconfig_win.go +++ b/server/cmd/preconfig_win.go @@ -12,31 +12,44 @@ import ( ) const ( - EsSystemRequired = 0x00000001 - EsContinuous = 0x80000000 + EsSystemRequired = 0x00000001 + EsAwaymodeRequired = 0x00000040 // Added for future improvements + EsContinuous = 0x80000000 ) -var pulseTime = 1 * time.Minute +var pulseTime = 60 * time.Second func Preconfig(kill bool) { go func() { // don't sleep/hibernate windows kernel32 := syscall.NewLazyDLL("kernel32.dll") setThreadExecStateProc := kernel32.NewProc("SetThreadExecutionState") + currentExecState := uintptr(EsContinuous) + normalExecutionState := uintptr(EsContinuous) + systemRequireState := uintptr(EsSystemRequired | EsContinuous) pulse := time.NewTicker(pulseTime) for { select { case <-pulse.C: { - send := false + systemRequired := false for _, torrent := range torr.ListTorrent() { if torrent.Stat != state.TorrentInDB { - send = true + systemRequired = true break } } - if send { - setThreadExecStateProc.Call(uintptr(EsSystemRequired)) + if systemRequired && currentExecState != systemRequireState { + // Looks like sending just EsSystemRequired to clear timer is broken in Win11. + // Enable system required to avoid the system to idle to sleep. + currentExecState = systemRequireState + setThreadExecStateProc.Call(systemRequireState) + } + + if !systemRequired && currentExecState != normalExecutionState { + // Clear EXECUTION_STATE flags to disable away mode and allow the system to idle to sleep normally. + currentExecState = normalExecutionState + setThreadExecStateProc.Call(normalExecutionState) } } } From 0673d3102ec50c7ec0fb2318709aac9a2776147a Mon Sep 17 00:00:00 2001 From: Anton Potekhin Date: Thu, 27 Apr 2023 09:02:08 +0300 Subject: [PATCH 2/2] Fixed prevention of sleep. --- server/cmd/preconfig_win.go | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/server/cmd/preconfig_win.go b/server/cmd/preconfig_win.go index 2de0405..ca31f4f 100644 --- a/server/cmd/preconfig_win.go +++ b/server/cmd/preconfig_win.go @@ -4,6 +4,7 @@ package main import ( + "runtime" "syscall" "time" @@ -21,12 +22,14 @@ var pulseTime = 60 * time.Second func Preconfig(kill bool) { go func() { + // need work on one thread because SetThreadExecutionState sets flag to thread. We need set and clear flag for same thread. + runtime.LockOSThread() // don't sleep/hibernate windows kernel32 := syscall.NewLazyDLL("kernel32.dll") setThreadExecStateProc := kernel32.NewProc("SetThreadExecutionState") currentExecState := uintptr(EsContinuous) normalExecutionState := uintptr(EsContinuous) - systemRequireState := uintptr(EsSystemRequired | EsContinuous) + systemRequireState := uintptr(EsSystemRequired | EsContinuous) pulse := time.NewTicker(pulseTime) for { select {