-
-
Notifications
You must be signed in to change notification settings - Fork 1.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Disable the RTC alarm on shutdown #6211
Conversation
@Frenzie: Shouldn't koreader/frontend/device/kobo/device.lua Lines 569 to 571 in 03140f5
be using
EDIT: Or koreader/frontend/device/kobo/device.lua Line 342 in 03140f5
|
That's a random 2AM PR after strace'ing Nickel during a sane shutdown, now that we can reliably trigger those via NickelMenu ;). EDIT: Experiments which answered another question I had: no, Nickel doesn't have a SIGTERM handler :(. There's no nice graceful closing of the dbs on SIGTERM :/. |
@Frenzie: Also, rtcwake disables the alarm interrupt as soon as it wakes up. I guess this wouldn't make much sense for us, since we re-set a new alarm at that point, right? |
Also, nothing ever uses WakeupMgr's |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not much code to review :)
(I don't really know much about that RTC stuff, but I guess that if something more is done just before poweroff, it can't hurt :)
Wasn't there some issue recently, here or on mobileread, where someone had his device auto waking up during the night? I have the following code in my private patch, no issue noticed. But just to be sure, does it look sane to you, and compatible with the core code using if self.auto_suspend_sec > 0 then
-- On programme une sortie du standby pour l'autosuspend
-- Note : s'assurer que auto_standby_timeout_seconds < auto_suspend_timeout_seconds
-- On retranche self.auto_standby_sec car il s'est passé ce temps depuis last action
local wake_in_sec = self.auto_suspend_sec - self.auto_standby_sec
self:mylog(" programming wakealarm for in ".. wake_in_sec)
-- os.execute('echo 0 > /sys/class/rtc/rtc0/wakealarm ; echo +'.. wake_in_sec ..' > /sys/class/rtc/rtc0/wakealarm')
-- Refait en pur lua pour éviter problème avec fork si memory leak :
self:_writeToSysFile("/sys/class/rtc/rtc0/wakealarm", "0")
self:_writeToSysFile("/sys/class/rtc/rtc0/wakealarm", "+"..wake_in_sec)
end
-- os.execute('echo standby > /sys/power/state ; echo 0 > /sys/class/rtc/rtc0/wakealarm')
-- Refait en pur lua pour éviter problème avec fork si memory leak :
self:_writeToSysFile("/sys/power/state", "standby")
-- (là, on est sorti du standby)
self:_writeToSysFile("/sys/class/rtc/rtc0/wakealarm", "0") (that "autostandby" of mine is some state I trigger after 20s of inactivity where I just let the touchscreen enabled - so a touch wakes it up) |
On the laptop right now, but (The sysfs interface is not available on Mk <= 5, hence the ioctl's, which work everywhere ;)). |
@NiLuJe Possibly, I didn't test it in too much detail besides the basics (i.e., standby for a bit and then auto wake up a little while later to shut down) although I believe scheduling further wakeups and such was working as intended. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍
@NiLuJe : regarding my snippet above #6211 (comment), actually some more complex bits of code than that, that seem to no longer work fine since you shuffle around all the clocks :) Also, does the UIManager/linux monotonic time adjusts itself so it can quickly catch the duration spent sleeping? Bit confused about all that at this time - but if you have any idea, thanks :) |
@poire-z: Yep, on Linux, MONOTONIC doesn't tick during suspend. So your understanding is correct, anything scheduled before suspend will run on resume in the same conditions as if a suspend had never happened. (i.e., whereas before, most likely every scheduled tasks would have expired and run on resume). You'd have to get me more context around where your patch actually applies to tell you what might be happening ;). As for |
Well, I'm very edge-casey with all this.
The issue is that I catch the tap in :handleInput() : you set self._now at top, then you Input:waitEvent() - then I tap and I catch the event in my self:_resetAutoSuspendTimer() before the regular :handleInputEvent() - so, possibly after the delay spent in waitEvent(), which might be 5 seconds. My original ugly code for context: @@ -1616,10 +1651,14 @@
-- delegate each input event to handler
if input_events then
+ self:_resetAutoStandbyTimer() -- me
+ self:_resetAutoSuspendTimer() -- me kept back 20170628
-- Handle the full batch of events
for __, ev in ipairs(input_events) do
self:handleInputEvent(ev)
end
+ self:_resetAutoStandbyTimer() -- me: do it also after, if handling took time
+ self:_resetAutoSuspendTimer() -- me kept back 20170628
end
if self.looper then
@@ -1794,5 +1833,710 @@
-- "me kept back 20170628" : remis logique AutoSuspend supprimee,
-- et externalisee dans plugin par Hzj-jie 20170623 :
-- https://github.com/koreader/koreader/commit/7d2ed4c3d0f61330a92ecf5a944eeedbd91c45be
-- me kept back 20170628
-- Kobo does not have an auto suspend function, so we implement it ourselves.
function UIManager:_initAutoSuspend()
local function isAutoSuspendEnabled()
return Device:isKobo() and self.auto_suspend_sec > 0
end
local sec = G_reader_settings:readSetting("auto_suspend_timeout_seconds")
if sec then
self.auto_suspend_sec = sec
else
-- default setting is 60 minutes
self.auto_suspend_sec = 60 * 60
end
if isAutoSuspendEnabled() then
self.auto_suspend_action = function()
self:mylog("in auto_suspend_action") -- me
-- me : par sécurité : logiquement, on ne devrait pas avoir programmé
-- plusieurs fois auto_suspend_action, mais bon, sait-on jamais
self:unschedule(self.auto_suspend_action)
local now = os.time()
-- Do not repeat auto suspend procedure after suspend.
if self.last_action_sec + self.auto_suspend_sec <= now then
-- self:suspend()
-- me: on éteind juste l'éclairage, et on délai le vrai suspend de 30 secondes,
-- qu'on puisse le canceller si on s'était mis à rêver
self:mylog(" suspending pre-stage")
-- On fait comme KoboPowerD:beforeSuspend() :
Device.powerd.fl:setBrightness(0) -- is_fl_on & fl_intensity conservent leurs valeurs
self:_stopAutoStandby() -- pour ne pas passer en standby d'ici là
self:mylog(" scheduling real_suspend_action in 30")
self:scheduleIn(30, self.real_suspend_action)
self.real_suspend_scheduled = true
else
self:mylog(" scheduling auto_suspend_action in " .. (self.last_action_sec + self.auto_suspend_sec - now))
self:scheduleIn(
self.last_action_sec + self.auto_suspend_sec - now,
self.auto_suspend_action)
end
end
self.real_suspend_scheduled = false -- me
self.real_suspend_action = function()
self:mylog(" in real_suspend_action")
self.real_suspend_scheduled = false
-- Au choix : vrai suspend avec screensaver :
-- self:suspend()
-- Ou bien : standby avec lock :
self:standbyAndLockInput()
end
function UIManager:_startAutoSuspend()
self:mylog("in _startAutoSuspend") -- me
self.last_action_sec = os.time()
self:nextTick(self.auto_suspend_action)
end
dbg:guard(UIManager, '_startAutoSuspend',
function()
assert(isAutoSuspendEnabled())
end)
function UIManager:_stopAutoSuspend()
self:mylog("in _stopAutoSuspend") -- me
self:unschedule(self.auto_suspend_action)
end
function UIManager:_resetAutoSuspendTimer()
-- self:mylog("in _resetAutoSuspendTimer") -- me
self.last_action_sec = os.time()
-- me : on nettoie si action alors qu'on a programmé le vrai suspend
if self.real_suspend_scheduled then
self:unschedule(self.real_suspend_action)
self.real_suspend_scheduled = false
-- On remet la lumière si elle était là avant
-- On fait comme KoboPowerD:afterResume() :
if Device.powerd.is_fl_on then
Device.powerd.fl:setBrightness(Device.powerd.fl_intensity)
end
self:_startAutoSuspend() -- et on remet l'autosuspend
self:_startAutoStandby() -- et on remet l'autostandby
-- pour que le handler discard le touch qu'on vient de faire
-- pour rallumer (on discard LES events (touch, release))
self:discardEvents(true)
end
end
self:_startAutoSuspend()
else
self._startAutoSuspend = noop
self._stopAutoSuspend = noop
end
end
UIManager._resetAutoSuspendTimer = noop -- me kept back 20170628
-- me : pour écrire dans fichier système plutôt que os.execute("echo 1 > /sys/toto")
-- qui est sujet à problème si memory leak et fork impossible
function UIManager:_writeToSysFile(sysfile, value)
local f, re, err_msg, err_code
-- logger.dbg("got to write '"..value.."' to "..sysfile)
f = io.open(sysfile, "w")
if not f then
logger.err("Cannot open ", sysfile, " for writing", value)
return false
end
re, err_msg, err_code = f:write(value.."\n")
-- logger.dbg("Wrote", value, "to", sysfile, "returned", re)
if not re then
logger.err("Write error to", sysfile, " for writing", value, ":", err_msg, err_code)
io.close(f)
return false
end
io.close(f)
return true
end
-- me : autoStandby (ça délaie le changement de pages de ~500ms à 1.5s,
-- mais activable / désactivable via setting auto_standby_timeout_seconds=0)
function UIManager:_initAutoStandby()
local function isAutoStandbyEnabled()
return Device:isKobo() and self.auto_standby_sec > 0
end
local sec = G_reader_settings:readSetting("auto_standby_timeout_seconds")
if sec then
self.auto_standby_sec = sec
else
self.auto_standby_sec = 0 -- default = 0 => not enabled
end
if isAutoStandbyEnabled() then
self.auto_standby_action = function()
self:mylog("in auto_standby_action")
-- me : par sécurité : logiquement, on ne devrait pas avoir programmé
-- plusieurs fois auto_suspend_action, mais bon, sait-on jamais
self:unschedule(self.auto_standby_action)
local now = ffiUtil.gettime()
if self.last_wakeaction_sec + self.auto_standby_sec <= now then
-- Si wifi enabled, on ne fait juste pas les opérations systèmes,
-- c'est plus simple que de trouver où mettre des stop/startAutoStandby
-- pour le désactiver pendant le WIFI
if not self:isWifiEnabled() then
if self.auto_suspend_sec > 0 then
-- On programme une sortie du standby pour l'autosuspend
-- Note : s'assurer que auto_standby_timeout_seconds < auto_suspend_timeout_seconds
-- On retranche self.auto_standby_sec car il s'est passé ce temps depuis last action
local wake_in_sec = self.auto_suspend_sec - self.auto_standby_sec
self:mylog(" programming wakealarm for in ".. wake_in_sec)
-- os.execute('echo 0 > /sys/class/rtc/rtc0/wakealarm ; echo +'.. wake_in_sec ..' > /sys/class/rtc/rtc0/wakealarm')
-- Refait en pur lua pour éviter problème avec fork si memory leak :
self:_writeToSysFile("/sys/class/rtc/rtc0/wakealarm", "0")
self:_writeToSysFile("/sys/class/rtc/rtc0/wakealarm", "+"..wake_in_sec)
end
self:updateStateStats("autostandby")
-- Pas la peine de logguer les autostandby, y'en a trop, on saure avec StateStats
-- os.execute('echo standby > /sys/power/state ; echo 0 > /sys/class/rtc/rtc0/wakealarm')
-- Refait en pur lua pour éviter problème avec fork si memory leak :
self:_writeToSysFile("/sys/power/state", "standby")
-- (là, on est sorti du standby)
self:_writeToSysFile("/sys/class/rtc/rtc0/wakealarm", "0")
self:updateStateStats("active")
end
self:_startAutoStandby() -- on redémarre l'auto standby
else
self:mylog(" scheduling auto_standby_action in " .. (self.last_wakeaction_sec + self.auto_standby_sec - now))
self:scheduleIn(
self.last_wakeaction_sec + self.auto_standby_sec - now,
self.auto_standby_action)
end
end
function UIManager:_startAutoStandby()
self:mylog("in _startAutoStandby")
self.last_wakeaction_sec = ffiUtil.gettime()
self:nextTick(self.auto_standby_action)
end
dbg:guard(UIManager, '_startAutoStandby',
function()
assert(isAutoStandbyEnabled())
end)
function UIManager:_stopAutoStandby()
self:mylog("in _stopAutoStandby")
self:unschedule(self.auto_standby_action)
end
function UIManager:_resetAutoStandbyTimer()
-- self:mylog("in _resetAutoStandbyTimer")
self.last_wakeaction_sec = ffiUtil.gettime()
end
self:_startAutoStandby()
logger.info("auto-standby enabled ("..self.auto_standby_sec.."s)")
else
logger.info("auto-standby disabled")
self._startAutoStandby = noop
self._stopAutoStandby = noop
end
end
UIManager._resetAutoStandbyTimer = noop I fixed my issues with these additional hacks: @@ -1917,6 +1917,7 @@
self:_startAutoStandby() -- et on remet l'autostandby
-- pour que le handler discard le touch qu'on vient de faire
-- pour rallumer (on discard LES events (touch, release))
+ self._now = TimeVal:now()
self:discardEvents(true)
end
end
@@ -1997,8 +1998,13 @@
-- (la, on est sorti du standby)
self:_writeToSysFile("/sys/class/rtc/rtc0/wakealarm", "0")
self:updateStateStats("active")
+ self:_startAutoStandby() -- on redemarre l'auto standby
+ if self.auto_suspend_sec > 0 then
+ self.auto_suspend_action() -- ça peut stoper l'auto standby
+ end
+ else
+ self:_startAutoStandby() -- on redemarre l'auto standby
end
- self:_startAutoStandby() -- on redemarre l'auto standby
else
self:mylog(" scheduling auto_standby_action in " .. (self.last_wakeaction_sec + self.auto_standby_sec - now))
self:scheduleIn( |
Depends on koreader/koreader-base#1106
This change is