Bugzilla – Bug 8141
Macintosh: Prevent Sleep While Playing
Last modified: 2013-09-18 18:45:29 UTC
My Squeezebox will properly wake my iMac from sleep mode when I turn on the Squeezebox. However, while the Squeezebox is playing music, the iMac will go to sleep at the inactivity setting in the "Energy Saver" panel of System Prefences. This causes the music to stop abruptly and the Squeezebox will turn off. Simply disabling the computer from ever going to sleep does not seem like a reasonable work-around. It seems to me that SqueezeCenter should be able to prevent the iMac from going to sleep while it is streaming music.
I see the same behaviour for my Mac Mini. The strange thing is that it seems that it holds the session longer then my Energy Saving settings.
Steven, can you have a look at this one please
As far as I know SqueezeCenter does not have a mechanism on Mac OS X to prevent sleep while streaming audio thus making this an enhancement request. There are a few user suggested methods involving scripts mentioned on the forums however. Michael, does this sound correct to you?
Yes, the plugin we have is Windows only. But I'm not even sure why we need to do this: shouldn't standby be prevented by eg. any disk access? Thus playing a new track every few minutes would prevent it, unless the track is longer than the standby timeout?
Michael, I agree that the mere act of streaming on Mac OS X should prevent sleep but in practice this does not always appear to be the case. Perhaps we could integrate Jiggler in SqueezeCenter as suggested in this thread: http://forums.slimdevices.com/showpost.php?p=247882&postcount=4 Jiggler is available at: http://www.sticksoftware.com/software/Jiggler.html If you are interested in this functionality being included in a future SqueezeCenter release please vote for this bug.
(In reply to comment #5) > Perhaps we could integrate Jiggler in SqueezeCenter... I think that Caffeine is a more elegant solution that Jiggler (which sounds like a hack, in the negative sense). Caffeine can be investigated here: http://www.lightheadsw.com/caffeine/
Would it be possible to make the SqueezeBox firmware send a network packet to the SqueezeCenter server periodically to keep it from going to sleep? After all, the SqueezeBox already sends some kind of packet that causes the "Wake on LAN" server setting to wake up from sleep. Can't this same packet be sent periodically (i.e. every 5 minutes) to keep the server computer from going to sleep?
Now with Mountain Lion there is a new aggressive sleep policy that prevents the third party attempts at resolving this long-standing problem from working. It is now a significant issue. ML now uses Power Assertions to prevent standby. These need to be set when a player is connected to prevent standby. See the ML caffeinate command for clues
Here are my notes on this from the forums OSX Mountain Lion (ML) has an idle sleep policy that requires apps to set power assertions if they want to prevent sleep after the period set in Energy Saver - see for example http://arstechnica.com/apple/2012/07/os-x-10-8/18/. This means that utilities I relied on under Lion - Caffeine and ReallyPreventStandby plugin for LMS no longer work. There is a new command line utility in ML that might give some pointers to a way forward: caffeinate – prevent the system from sleeping on behalf of a utility This allows you to either directly prevent your Mac from falling asleep for a specific period of time (e.g. an hour): caffeinate -u -t 3600 or allows a command to run for a prolonged period without the automatic (and, since 10.8, rather aggressive) sleep function kicking in caffeinate -s any-long-running-command -with arguments The source of caffeinated seems to be here: http://opensource.apple.com/source/P...ment-271.25.8/ .... Seems like these new assertions could finally give a reliable solution to LMS sleep issues under OSX if they could be incorporated somehow. ......
Logitech should make some effort here. There are many people with Macs out there and more and more people will be using Mountain Lion. This should be a priority fix
This is an example of code that sets the assertion to prevent sleep. Taken from the open source of named (Bind): IOPMAssertionCreateWithName(kIOPMAssertionTypeDenySystemSleep, kIOPMAssertionLevelOn, CFSTR("org.isc.named.denysystemsleep"), &named_IOPMSleepAssertion); There would be a corresponding call to re-enable sleep once LMS was no longer currently playing to a SB player. The command pmset -g can be used to see if sleep is being prevented and if so by which pid. Apple have finally given us a solution to this long-standing problem. Please let's fix it.
Nonnoroger - would you say that running "caffeinate -i -t 36000" from LMS every now and then would do it? Interestingly I did find the tool's man page on my 10.7 systems, but not the binary itself. It only seems to be present on 10.8. Would you be willing and able to manually replace a folder inside the LMS installation to test some code I've been playing with? I don't have a real 10.8 system yet (only a VM - which behaves slightly different in this regard).
(In reply to comment #12) > Nonnoroger - would you say that running "caffeinate -i -t 36000" from LMS > every now and then would do it? > > Interestingly I did find the tool's man page on my 10.7 systems, but not the > binary itself. It only seems to be present on 10.8. > > Would you be willing and able to manually replace a folder inside the LMS > installation to test some code I've been playing with? I don't have a real > 10.8 system yet (only a VM - which behaves slightly different in this > regard). Many thanks for the suggestion and the offer Michael. I am, of course, happy to help in testing solutions. We are going to need to be a bit smarter about it than this though I suspect. Caffeinate prevents standby for as long as it runs. So it would have to be forked, or run as a system command with a trailing &. Giving it a timeout via -t 36000 would make sure that sleep would eventually be allowed if something went wrong with the logic elsewhere, but LMS would really need to kill the caffeinate process once no players were connected - perhaps after a suitable grace period. So I do not see real need to have a timeout period set at all. I have now had time to look at Gordon Harris's ReallyPreventStandby plugin. I am ruuning it with caffeinate -i as the prevent idle command and pkill caffeinate as the allow caffeinate command with these set as toggles. Contrary to what Gordon remembered, the toggle setting means that the commands only need to be called once which is what we need in this case. I have only tested so far the case of preventing standby when any player is powered on - as set in the settings for the plugin. Debugging the plugin and analyzing the code convinced me that in this case at least, the call of _killInhibitCmd() in the plugin's _hasResumed() is inappropriate, at least with these settings. It was having the effect of killing the caffeinate that had been started on resume - by a Touch sending its WOL to the server. I have now deleted that call and have found the operation to be much improved. However, occasionally the Mac Mini still goes back to sleep before the plugin has had a chance to make that call of caffeinate. If a Mountain Lion system is woken by an interactive user, say at the keyboard, it will stay awake until the idle timer expires - in my case 10 minutes. If it is woken by WOL it ignores the idle timer and goes back to sleep more or less straight away - unless the appropriate power management assertion is made in time. ReallyPreventStandby depends on polling the state of the system at 60 second intervals. If it has resumed, if players are busy, or if the server is scanning for import it calls the prevent standby command - in the case of my settings this is caffeinate -i. It seems that ML will sometimes be sent back to sleep before that call of caffeinate, in a separate process, has had time to set the assertion. My firm view is that the source of caffeinate I found, and other examples since, should only be used as an example of the code that needs to be used withing LMS itself. iTunes does this, as can be seen by running pmset -g when it is playing and not playing. Ideally we should avoid the need for polling and take the appropriate action whenever sleep needs to be prevented or can be allowed again. (There might need be a grace period though before allowing it again as offered now by ReallyPreventStandby - especially if the Mac is allowed to sleep while players are left on.) If hooks could be provided for this within LMS, platform-specific code could then be called. (It might be that some third-party plugins or Apps may themselves need to invoke these - I am thinking of Triode's Spotify and BBC Player for example but again, if sleep was prevented as long as any SB was on this should not be necessary.) I am hoping that the code called via the hooks could be implemented in OSX via the PerlObjectiveC bridge. I will carry on looking at ReallyPreventStandby but I am now more or less convinced that in the case of Mountain Lion we will have to set the assertions and release them within LMS itself and not by invoking new processes to to run other commands. Thanks again, and sorry for the long post. Your offer came just as I was about to post much of the above to the relevant thread on the third-party forum. I will still do that for those only following that thread.
Created attachment 7680 [details] Keep OSX alive Ok, here's the deal: this .zip file contains a drop-in replacement for the existing PreventStandby plugin. It adds support for OSX. I've re-factored the main plugin to better support different platforms, as the Windows method to keep the system alive is pretty different from OSX. The OSX implementation uses the "pmset noidle" utility available in OSX 10.2+. There's one additional check added to the _playerBusy test: $client->lastActivityTime carries a timestamp of the last activity on given player. This includes navigating menus on the devices itself, control through the web UI or smartphone apps. This gives a much more accurate result than isPlaying alone. It will hopefully compensate for OSX' lack of waking up through disk activity. On a default OSX installation just extract the file to /Library/PreferencePanes/Squeezebox.prefPane/Contents/server/Slim/Plugin/, restart your LMS. Then go to Settings/Plugins to make sure the plugin is enabled. If not, do so, restart LMS and see what happens. Though I've only tested in 7.8 it should be compatible with 7.7 too.
Great progress. Just a quick bit of feedback before I try it as I see you are using Proc::Background: As I recently pointed out on Triode's Spotify forum, there is a long-standing bug in Proc::Background in that die() sends a signals in the order HUP, QUIT, INT so causing a core dump unless the QUIT is caught. I have tested a new version of spotifyd for Triode in which he catches QUIT and exits but since we cannot do that with pmset I will alter my Proc::Background from LMS to change the order of INT and QUIT. Really TERM should be in there first as that is the normal signal for terminating a Unix process. I strongly suggest that you fix this in the next release of LMS.
Created attachment 7681 [details] Enable PreventStandby on OSX Thanks for the hint. The core dump you mention: does it happen to LMS itself, or does it happen when you shut down LMS?
The content of attachment 7680 [details] has been deleted by Michael Herger <michael@slimdevices.com> without providing any reason. The token used to delete this attachment was generated at 2012-08-24 07:22:34 PDT.
(In reply to comment #16) > Created attachment 7681 [details] > Enable PreventStandby on OSX > > Thanks for the hint. The core dump you mention: does it happen to LMS > itself, or does it happen when you shut down LMS? In the case of Triode's Spotify, spotifyd core dumped when LMS was stopped as he uses die to terminate it. In the case of your proposed new version of Prevent System Standby, you use die to terminate pmset noidle. So pmset might have core dumped when you allow system standby - I was being cautious as I do not know if pmset catches QUIT but I suspect it does not. I have edited the version that comes with LMS in /Library/PreferencePanes/Squeezebox.prefPane/Contents/server/CPAN/Proc/Background/Unix.pm From: foreach my $signal (qw(HUP QUIT INT KILL)) { To: foreach my $signal (qw(HUP TERM INT KILL)) { as QUIT normally causes the receiving procees to generate a core dump.
(In reply to comment #17) > The content of attachment 7680 [details] has been deleted by > Michael Herger <michael@slimdevices.com> > without providing any reason. > > The token used to delete this attachment was generated at 2012-08-24 > 07:22:34 PDT. No need to delete this because of my earlier comment - the issue is with Proc::Background not with this version of PreventStandby.
(In reply to comment #14) > Created attachment 7680 [details] > Keep OSX alive > > Ok, here's the deal: this .zip file contains a drop-in replacement for the > existing PreventStandby plugin. It adds support for OSX. Will need to update comments in header to reflect that before release. > I've re-factored the main plugin to better support different platforms, as > the Windows method to keep the system alive is pretty different from OSX. > The OSX implementation uses the "pmset noidle" utility available in OSX > 10.2+. Good idea. Nice to have the process id so it can be terminated specifically. I suggest you include the process id in the logs. For some reason, pmset -g is not showing the process preventing sleep. > There's one additional check added to the _playerBusy test: > $client->lastActivityTime carries a timestamp of the last activity on given > player. This includes navigating menus on the devices itself, control > through the web UI or smartphone apps. This gives a much more accurate > result than isPlaying alone. It will hopefully compensate for OSX' lack of > waking up through disk activity. Additional check is very welcome, (but not clear how it compensates OSX' lack of waking up through disk activity. We are awake anyway or we would not be here to do the test). On first go, there did seem to be one glitch in that it thought one of my switched-off Touches was busy. But with this in sub checkClientActivity if ( Slim::Music::Import->stillScanning() || _hasResumed($currenttime) || _playersBusy() ) { we still have the problem of other reasons for resume, apart from SB activity, causing the wake-up. Would it make sense to get the result of _playersBusy() once before the if and then pass it to _hasResumed as an extra argument? Then _hasResumed could check if the resume was due to LMS client activity? In Strings.pm is said: It will also prevent the system from prematurely going into standby two minutes after wake-on-lan. But as my log shows, it is not two minutes - it is the current period from settings (I have mine set to 5 minutes). This is why the activity test coupled with resume is so important. [12-08-24 15:53:25.4969] Slim::Plugin::PreventStandby::Plugin::_hasResumed (190) System has resumed... [12-08-24 15:53:25.4974] Slim::Plugin::PreventStandby::Plugin::checkClientActivity (125) Resetting idle counter. 5 minutes left in allowed idle period. [12-08-24 15:53:25.4976] Slim::Plugin::PreventStandby::Plugin::checkClientActivity (142) Preventing System Standby... [12-08-24 15:53:25.4979] Slim::Plugin::PreventStandby::OSX::setBusy (40) Injecting some caffein to keep system alive: '/usr/bin/pmset noidle' [12-08-24 15:54:25.0027] Slim::Plugin::PreventStandby::Plugin::checkClientActivity (132) Incrementing idle counter. 4 minutes left in allowed idle period. [12-08-24 15:54:25.0031] Slim::Plugin::PreventStandby::Plugin::checkClientActivity (142) Preventing System Standby... [12-08-24 15:55:25.0022] Slim::Plugin::PreventStandby::Plugin::checkClientActivity (132) Incrementing idle counter. 3 minutes left in allowed idle period. [12-08-24 15:55:25.0025] Slim::Plugin::PreventStandby::Plugin::checkClientActivity (142) Preventing System Standby... [12-08-24 15:56:25.0021] Slim::Plugin::PreventStandby::Plugin::checkClientActivity (132) Incrementing idle counter. 2 minutes left in allowed idle period. [12-08-24 15:56:25.0026] Slim::Plugin::PreventStandby::Plugin::checkClientActivity (142) Preventing System Standby... [12-08-24 15:57:25.0025] Slim::Plugin::PreventStandby::Plugin::checkClientActivity (132) Incrementing idle counter. 1 minutes left in allowed idle period. [12-08-24 15:57:25.0028] Slim::Plugin::PreventStandby::Plugin::checkClientActivity (142) Preventing System Standby... [12-08-24 15:58:25.0021] Slim::Plugin::PreventStandby::Plugin::checkClientActivity (147) Players have been idle for 5 minutes. Allowing System Standby... There is a reference to what is effectively two minutes in _hasResumed but I confess to not understanding the logic here. But otherwise this seems to work just fine on Mountain Lion. It will be great to have an official plugin for this for OSX as well as Windows. Is there not a need for it on other platforms? Will continue testing over the weekend.
(In reply to comment #14) > Though I've only tested in 7.8 it should be compatible with 7.7 too. pmset has has the noidle option since 10.5 Leopard. Confirm by going to http://www.opensource.apple.com/ through the 10.5 link, PowerManagement=137, pmset. pmset.1, the source of the manual page, includes: .Ar noidle - while continuousy running, pmset prevents idle sleep. The source pmset.c is also there. For anyone interested, it shows how to prevent idle sleep on OSX by making the appropriate power assertion in the definition of prevent_idle_sleep(void). Does not show how to enable it again as it assumes that pmset will just be terminated by an interactive user.
(In reply to comment #20) > But with this in sub checkClientActivity > > if ( Slim::Music::Import->stillScanning() || _hasResumed($currenttime) || > _playersBusy() ) { > > we still have the problem of other reasons for resume, apart from SB > activity, causing the wake-up. Would it make sense to get the result of > _playersBusy() once before the if and then pass it to _hasResumed as an > extra argument? > Then _hasResumed could check if the resume was due to LMS client activity? Hang-on though. With your new improved _playersBusy() do we need _hasResumed($currenttime) at all?
On system resume, for whatever reason, including pressing a key on the keyboard, at the first call of _playersBusy it seems as though one of my players always seems busy. It is always the same one that is named in the log. I have not touched it for hours. Just wondering if in _playersBusy: if ( $client->isUpgrading() || $client->isPlaying() || (Time::HiRes::time() - $client->lastActivityTime <= INTERVAL) ) { the result returned by time() is off after a period of sleep? Cannot see where Time::HiRes is defined to see what it is doing. because of this, I get the grace period kicking in and pmset noidle runs. But after that, on subsequent calls, no players are reported busy. Testing this with the setting that idle is allowed if players are turned on, without me touching any players - just resuming from the keyboard. To test _playersBusy properly I have also removed the call of _hasResumed.
> Hang-on though. With your new improved _playersBusy() do we need > _hasResumed($currenttime) at all? I don't think so. As for the activity after waking up: could you add a log statement to get the result of (Time::HiRes::time() - $client->lastActivityTime and the absolute value of lastActivityTime?
Created attachment 7682 [details] Commented debug output around resume
Created attachment 7683 [details] Packet trace around resume Wireshark/tcpdump packet trace
Created attachment 7684 [details] Content of first TCP session
Created attachment 7685 [details] Content of second TCP session
Created attachment 7686 [details] Version of _playersBusy for debug
(In reply to comment #18) > (In reply to comment #16) > > Created attachment 7681 [details] > > Enable PreventStandby on OSX > > > > Thanks for the hint. The core dump you mention: does it happen to LMS > > itself, or does it happen when you shut down LMS? > > In the case of Triode's Spotify, spotifyd core dumped when LMS was stopped > as he uses die to terminate it. > > In the case of your proposed new version of Prevent System Standby, you use > die to terminate pmset noidle. So pmset might have core dumped when you > allow system standby - I was being cautious as I do not know if pmset > catches QUIT but I suspect it does not. > > I have edited the version that comes with LMS in > /Library/PreferencePanes/Squeezebox.prefPane/Contents/server/CPAN/Proc/ > Background/Unix.pm > > From: > foreach my $signal (qw(HUP QUIT INT KILL)) { > > To: > foreach my $signal (qw(HUP TERM INT KILL)) { > > as QUIT normally causes the receiving procees to generate a core dump. The order should really have TERM first. Triode catches HUP in spotifyd which was why it was getting the QUIT first leading to the core dump.
Realised after a loooong time waiting for my Mac to be allowed to sleep that the proposed _playersBusy check of activity always succeeds if a browser is connected to the LMS Settings page on the Information tab!
Michael: if you're really going to flesh out PreventStandby to support multiple platforms, may I suggest you take the time to fill in the other big missing piece? I.e., have PreventStandby schedule a system wake-up for the next pending Squeezebox alarm when the plugin stops inhibiting sleep? See the current beta of the SrvrPowerCtrl plugin for code for doing this on windows/linux/osx.
..though I suppose this is only important for the installed base of SB2s/SB3s/SBRs/Transporters. The Booms/Radios/Touches have backup alarms, don't they.
(In reply to comment #32) > Michael: if you're really going to flesh out PreventStandby to support > multiple platforms, may I suggest you take the time to fill in the other big > missing piece? I.e., have PreventStandby schedule a system wake-up for the > next pending Squeezebox alarm when the plugin stops inhibiting sleep? See > the current beta of the SrvrPowerCtrl plugin for code for doing this on > windows/linux/osx. Echo that if this will allow the PowerSave plugin or something like it to work if the server had gone to sleep.
I'm not sure what you mean there. No plugin can work if the server has gone to sleep. But PreventStandby could optionally turn all the players "off" when it determines that the idle conditions have been met. Again, just like SrvrPowerCtrl and PowerSave do now.
(In reply to comment #35) > I'm not sure what you mean there. No plugin can work if the server has gone > to sleep. But PreventStandby could optionally turn all the players "off" > when it determines that the idle conditions have been met. Again, just like > SrvrPowerCtrl and PowerSave do now. Sorry - too late at night when I needed sleep myself. When I was testing, I had the PowerSave setting longer than the PreventStandby setting. When I saw your request, I thought have PreventStandby schedule a system wake-up to allow the SB's to be powered off. But of course, if the SB's are connected to LMS and not mysqueezebox.com then PreventStandby might as well, optionally, power-off the SBs when it stops preventing standby. (We must not forget in all this that stopping preventing standby does not mean that the server will go into standby. There may well be other processes that have set powere assertions in OSX, or there may just be an interactive user.)
Hmmmm. Thought I should look at PowerSave to see its definition of a player being idle: ==== # PowerSave will turn off a player after a specified amount of idle # time has elapsed. By default, idle time is defined as when a player # is not playing and no button presses have been received within the # specified time. The default idle time is 15 minutes. ==== Isn't this just what we need for _playersBusy? Or is it now too early in the morning?
Man... you've been busy! > On system resume, for whatever reason, including pressing a key on the > keyboard, at the first call of _playersBusy it seems as though one of my I guess that the re-connection after the server came back is considered an activity as reported by lastActivityTime. > players always seems busy. It is always the same one that is named in the > log. I have not touched it for hours. Those events are only logged for the first player where a condition applies. Then it exits the check. The order in which those player checks run are based on the MAC address. > Realised after a loooong time waiting for my Mac to be allowed to sleep that > the proposed _playersBusy check of activity always succeeds if a browser is > connected to the LMS Settings page on the Information tab! Yes, that page does poll for scan events. This polling is considered activity (would be the same on other systems where disk activity is preventing standby). The same applies to the main web page, where the player status is polling.
(In reply to comment #32) > Michael: if you're really going to flesh out PreventStandby to support > multiple platforms, may I suggest you take the time to fill in the other big > missing piece? I.e., have PreventStandby schedule a system wake-up for the > next pending Squeezebox alarm when the plugin stops inhibiting sleep? As you noticed yourself this would only be required for the old players (pre-Boom). Newer players should try WOL before the alarm. Is there a bug report for this?
(In reply to comment #39) > (In reply to comment #32) > > Michael: if you're really going to flesh out PreventStandby to support > > … > > As you noticed yourself this would only be required for the old players > (pre-Boom). Newer players should try WOL before the alarm. Is there a bug > report for this? More than 1 wake-up alarm can't hurt :) The feature would be needed for about anyone running its SBS server on a wifi machine. Also, on linux it is my experience that very often a wake-up vector will work from S3, but not from S5. Or the other way around. I think WOL+RTC is much better for alarm reliability than WOL alone, for all players. (Besides RTC capability has unique uses in itself, like scheduling batch tasks such as rescanning on Monday night.)
I think we had better try to solve one problem at a time. Michael asked if there was a bug report for this.
(In reply to comment #39) > As you noticed yourself this would only be required for the old players > (pre-Boom). Newer players should try WOL before the alarm. Is there a bug > report for this? I'll put together a version of PreventStandby based on your latest version, pulling in SrvrPowerCtrl's RTC wakealarm code, create a new bug, and post the code. For the windows wake code, PreventStandby would have to bundle my SCPowerTool.exe utility in order to schedule a system wake up. My C code is at http://srvrpowerctrl.googlecode.com/files/SCPowerTool_latest.zip. If Logitech wants to distribute the utility with PreventStandby, or fork my code and deliver its own, you have my permission...not that you need it...the code is GPL2.
Michael: if you want to extend PreventStandby to inhibit suspending on Linux desktops too, then you're free to include gsession-inhibit, the standby inhibitor I wrote in C for gnome. This code has stood up well and according to my tests, survived the transition from gnome 2.x to gnome 3.x and to Ubuntu's Unity desktop. Again the GPL2 source code for this C utility is included in the latest beta of ReallyPreventStandby: http://srvrpowerctrl.googlecode.com/svn/ReallyPreventStandby_beta.zip It's been some time since I looked at this code and I *think* that the squeezeboxserver user needs to have passwordless sudo permission via /etc/sudoers to execute this as root. The code includes a setup script that makes the sudoers change. I'm not a KDE user, so I'm unsure what one has to do to inhibit suspend on that desktop.
(In reply to comment #42) > (In reply to comment #39) > > As you noticed yourself this would only be required for the old players > > (pre-Boom). Newer players should try WOL before the alarm. Is there a bug > > report for this? > > I'll put together a version of PreventStandby based on your latest version, > pulling in SrvrPowerCtrl's RTC wakealarm code, create a new bug, and post > the code. If by latest version you mean the one attached to this Bug, that I have been testing, I suggest you wait as it is not ready. The test of _playersBusy is not working as expected. The call of _hasResumed should also be deleted. Waiting for Michael to say where he wants to go next with this.
> If by latest version you mean the one attached to this Bug, that I have been > testing, I suggest you wait as it is not ready. The test of _playersBusy is > not working as expected. The call of _hasResumed should also be deleted. What is not working in _playersBusy?
> It's been some time since I looked at this code and I *think* that the > squeezeboxserver user needs to have passwordless sudo permission via > /etc/sudoers to execute this as root. The code includes a setup script that > makes the sudoers change. Thanks for the offer. But to be honest I see little to no chance to see this included with the official builds. A tool which needs manual setup in Linux will never be accepted by our support.
(In reply to comment #45) > > If by latest version you mean the one attached to this Bug, that I have been > > testing, I suggest you wait as it is not ready. The test of _playersBusy is > > not working as expected. The call of _hasResumed should also be deleted. > > What is not working in _playersBusy? As I reported from my testing - it is always saying a player is busy even when it has not been touched. That is why you asked me to print out the times in the debug output!?
(In reply to comment #44) > If by latest version you mean the one attached to this Bug, that I have been > testing, I suggest you wait as it is not ready. The test of _playersBusy is > not working as expected. The call of _hasResumed should also be deleted. > > Waiting for Michael to say where he wants to go next with this. I'll make sure my wake-up code is independent of _playersBusy, with a separate GetNextAlarm.pm module and then code additions of SetWakeAlarm() functions in the various OS modules. In other words, I'll try to make this as painless as possible to add, if Michael wants to do it.
> As I reported from my testing - it is always saying a player is busy even > when it has not been touched. Not _always_, but whenever a WOL event happens. Yes, that's true, but not a show stopper imho. It potentially left the system running a few minutes longer than needed (worst case). In many cases when WOL happens the process triggering it would probably run this duration or longer anyway (eg. you're streaming a movie to your TV set, running a backup etc.).
(In reply to comment #46) > Thanks for the offer. But to be honest I see little to no chance to see this > included with the official builds. A tool which needs manual setup in Linux > will never be accepted by our support. No, of course not. I need to retest that code to make doubly sure that root privilege IS required to inhibit standby via the gnome session manager. It may be that this won't be an issue. But even if it is, no manual setup would be required, of course. The sudoers modification could easily be made part of the rpm and deb setup routines.
Actually, I think I'm remembering now. It's not root privilege that the squeezeboxserver user needs to run gsession-inhibit. Instead, it needs to execute gsession-inhibit in a regular gnome user's context. I.e.: # sudo -u 'some-gnome-user' gsession-inhibit $existing_gnome_session_id_from_env So it's *possible* that sudoers doesn't need to be touched at all during setup. Rather, the squeezeboxserver account just needs to be made a member of the appropriate gnome group on setup. But, again, I managed to get this working in the source to ReallyPreventStandby beta...which, obviously, I need to review.
(In reply to comment #49) > > As I reported from my testing - it is always saying a player is busy even > > when it has not been touched. > > Not _always_, but whenever a WOL event happens. Yes, that's true, but not a > show stopper imho. It potentially left the system running a few minutes > longer than needed (worst case). In many cases when WOL happens the process > triggering it would probably run this duration or longer anyway (eg. you're > streaming a movie to your TV set, running a backup etc.). Sorry Michael. When you said in reply ============= I guess that the re-connection after the server came back is considered an activity as reported by lastActivityTime. ============= I took that to mean you agreed the code is not doing what was intended to help distinguish between wake-ups by a LMS client and other wakeups. A Mac gets probes from Apple Tvs, from Airport base stations and the like and goes back to sleep after a few seconds. If it is going to stay on for several minutes just in case there is an interactive SB user, I for one will always be setting the option to prevent standby only if an SB is powered on and be done with it. As I said earlier, PowerSave can tell if a SB is idle or not. Is it worth looking at how it does its checks?
FYI Here is a section from last night's log of my Mac showing periodic RTC wakeups for system maintenance: I have commented to highlight the wake-up and sleep times. 27/08/2012 03:44:47.000 kernel[0]: RTC: Maintenance 2012/8/27 02:44:46, sleep 2012/8/27 00:56:59 The first time of 03:44:47.000 is in BST - one hour ahead of the UTC time shown as 02:44:46 27/08/2012 03:44:47.000 kernel[0]: Previous Sleep Cause: 5 27/08/2012 03:44:47.000 kernel[0]: 00000000 00000020 NVEthernet::setLinkStatus - not Active 27/08/2012 03:44:48.263 hidd[44]: MultitouchHID: device bootloaded 27/08/2012 03:44:49.000 kernel[0]: Ethernet [nvenet]: Link up on en0, 1-Gigabit, Full-duplex, Symmetric flow-control, Debug [796d,0000,0de1,000d,c5e1,2800] 27/08/2012 03:44:49.000 kernel[0]: 3b9aca00 00500030 NVEthernet::setLinkStatus - Active 27/08/2012 03:44:49.382 configd[17]: network changed: DNS* Proxy 27/08/2012 03:44:49.383 com.apple.launchd[1]: (com.apple.softwareupdatecheck.periodic) Throttling respawn: Will start in 8 seconds 27/08/2012 03:44:50.999 configd[17]: network changed: v4(en0+:10.13.7.180) DNS+ Proxy+ SMB+ 27/08/2012 03:44:56.000 kernel[0]: Graphics suppressed 9013 ms 27/08/2012 03:45:21.000 kernel[0]: 00000000 00000020 NVEthernet::setLinkStatus - not Active 27/08/2012 03:45:23.623 configd[17]: network changed: v4(en0-:10.13.7.180) DNS- Proxy- SMB- 27/08/2012 03:45:23.655 configd[17]: network changed: DNS* Proxy The Mac went back to sleep again, when exactly? 27/08/2012 05:33:13.000 kernel[0]: Wake reason: RTC (Alarm) 27/08/2012 05:33:13.000 kernel[0]: RTC: Maintenance 2012/8/27 04:33:12, sleep 2012/8/27 02:45:24 The last line says it went to sleep at 02:45:24 UTC So it was awake for 38 seconds from 02:44:46 UTC. Then there was another RTS Maintenance alarm at 04:33:12 UTC
Created attachment 7687 [details] A night with Prevent Standby Using the proposed test of _playersBusy. To help you see where I am coming from, please take some time to look at this server log which I have commented. No players actually touched or in use until 6:30am but Prevent Standby prevented standby frequently and without any need. When a player was turned on at 6:30 and menus used, the Mac was woken up, Prevent Standby noticed and was about to invoke pmset, when the Mac went back to sleep again before the new process could be spawned to run it. In my own case, I will probably leave the plugin just checking if players are turned on and use PowerSave to turn off the players if they are idle. But there is something odd in a situation where PowerSave knows players are idle but prevent Standby does not. Please be aware that I am out all day Tuesday 28th August as part of my holiday week.
Thinking about the issues we're seeing, and our thinking that _hasResumed was no longer required, I come to the conclusion that we were wrong. We still need it, but with the opposite meaning: on OSX we don't need to keep alive when coming out of standby, but we should ignore that first event, because players will always signal activity when they re-connect to the server.
(In reply to comment #55) > Thinking about the issues we're seeing, and our thinking that _hasResumed > was no longer required, I come to the conclusion that we were wrong. We > still need it, but with the opposite meaning: on OSX we don't need to keep > alive when coming out of standby, but we should ignore that first event, > because players will always signal activity when they re-connect to the > server. Brilliant! Why didn't I think of that? I can enjoy my lunch out now. Thanks!
(In reply to comment #56) > (In reply to comment #55) > > Thinking about the issues we're seeing, and our thinking that _hasResumed > > was no longer required, I come to the conclusion that we were wrong. We > > still need it, but with the opposite meaning: on OSX we don't need to keep > > alive when coming out of standby, but we should ignore that first event, > > because players will always signal activity when they re-connect to the > > server. > > Brilliant! Why didn't I think of that? > > I can enjoy my lunch out now. > > Thanks! Just hope it works when it is a player that causes the resume!
Created attachment 7688 [details] PreventStandby with support for OSX & Win32 This version uses the _hasResumed method to skip the first (or two) check after resume on OSX. This should help to prevent accidental keep alive when system was woken up due to some other activity than ours. In a border case where a user would set the timeout to 2 minutes or less, this could still have a negative side-effect. But in those cases 2 minutes delayed standby don't hurt too much either.
(In reply to comment #58) > Created attachment 7688 [details] > PreventStandby with support for OSX & Win32 > > This version uses the _hasResumed method to skip the first (or two) check > after resume on OSX. This should help to prevent accidental keep alive when > system was woken up due to some other activity than ours. > > In a border case where a user would set the timeout to 2 minutes or less, > this could still have a negative side-effect. But in those cases 2 minutes > delayed standby don't hurt too much either. Thanks Michael. I have done some testing. The news is mixed. (And we didn't enjoy our lunch either unfortunately - we had to send it back.) The good news is that we no longer have the plugin preventing standby when resume is not due to a SB player. Also, on some occasions, even if it is a player that has woken up the Mac Prevent Standby is preventing standby despite the test of resume. But I did have to insist sometimes by trying again to connect. The not so good news is that on several occasions I have had the Mac go more or less straight back to sleep even though it was woken up by a player. I see three potential reasons for this: 1. The busy test has been discounted because it was busy after a resume. 2. The check has not been done quickly enough given the polling interval. 3. The system goes back to sleep before pmset noidle has had a chance to run in its own process. Looking back at the server logs, on a few occasions it is the third case that has applied. The log shows the intention to inject a dose of caffeine, but before pmset has run, the Mac has gone back to sleep. This is the "race" I noticed with ReallyPreventStandby when I was using caffeinate as disscussed in the forum. One way to significantly reduce the chances of this happening is to run the code that pmset uses to set the power assertions directly (and unset them directly). We know pmset is open source. (Cases 2 and 3 are not independent of course. As you know, I have already suggested an event-based approach to manipulating the power assertions, rather than a polling approach. Perhaps that is something that could be considered in the future.) As for case 1, there is another test, instead of or as well as the test of resume that is available to us. That is simply to test if the player that appears to be busy is actually powered on. In all my overnight testing, for example, my players were all turned off (normal clock showing only). The false busy test was then the result of the reconnection after the resume but while the players were off. There is another situation I have realised from my testing where a test that the player that looks busy is actually on would help in power saving. A player can be apparently busy because the user has pressed buttons/touched the screen in order to turn the player off! There is no value on continuing to wait the set grace period if the player is off. (I should also mention that when LMS is restarted, even if the players are off, standby is prevented for the grace period because the reconnections are not discounted by the test of resume.) I suppose that there will be some users that leave their players on long after they have finished playing and long after any interaction with the player. You could keep the test of resume to cover that case, with the risk of then also discounting some tests of busy if the user had gone back to the player. Or you could choose to omit the test of resume on the grounds that a user who is happy keeping the players on is presumably not going to be worried about the server staying on an extra few minutes. This is what I recommend as it would give more reliability to the cases where the resume was caused by a player. There is one other situation in which the server is being prevented from sleeping that is not necessary or appropriate. That is if the player is connected to mysqueezebox.com and not to the local LMS. I used TuneIn radio in my testing to see PreventStandby preventing standby of the server even though it was not needed. It would be really helpful if this could be avoided. Your persistence with this is very much appreciated - is my suggestion of the power-being-on test acceptable to you?
I've committed my latest code to LMS 7.8. Please give it some thorough testing. Thanks!
I thought my testing was already pretty thorough. The Mac goes back to sleep after a network wake from a player before the pmset invoked by PreventStandby has time to set its power assertion. Attaching pmsetlog1.txt for the evidence - collected using pmset -g log Setting INTERVAL to 30 does allow pmset to get in in time. Attaching pmsetlog2.txt for comparison.
Created attachment 7689 [details] pmset -g log with INTERVAL = 60 Log has been commented to show the sequence of events.
(In reply to comment #62) > Created attachment 7689 [details] > pmset -g log with INTERVAL = 60 > > Log has been commented to show the sequence of events. What durations is your power management set to?
Created attachment 7690 [details] pmset -g log with INTERVAL = 30 Log commented again - notice that system does not get to announce idle sleep once it wakes up and starts playing. NB for both of these tests, I removed the code added by Michael to ignore player activity on system resume so as to improve the chances that pmset would be called in time.
(In reply to comment #63) > (In reply to comment #62) > > Created attachment 7689 [details] > > pmset -g log with INTERVAL = 60 > > > > Log has been commented to show the sequence of events. > > What durations is your power management set to? 10 minutes, but as I have explained several times now that is irrelevant. The system has already gone into idle sleep after the 10 minutes. You will see from the log that the SB player causes the MAC to go into Dark Wake state. powerd sets its own assertion to prevent system sleep for 30 seconds - this is not the same as idle sleep. When INTERVAL is 60, the system goes back to sleep not long after powerd releases its assertion.
Note that I am not simply recommending that INTERVAL is set to 30 in the released code. I have produced this just to help explain the situation with Mountain Lion. The critical situation is when the Mac is woken from sleep by a player. Once we prevent it from going promptly back to sleep, there is no problrm in keeping it awake as long as needed. There is no way I have found to extend the interval powerd uses beyond 30 sec - at least by published configuration settings. I have tried instead to achieve this effect by writing an OSX command line program to receive sleep notifications and then delay sleep. Unfortunately, the sleep notifications only arrive when the system wants to go into idle sleep after a period os user activity. They are not sent when the system goes back to sleep after a network wake. I can make the code for this program available in case anyone wants to try it - you will need the XCode development tools.
Created attachment 7691 [details] Diff against 7.8 branch adding activity events This patch adds a clientactivity event to LMS. This is being used by PreventStandby to reset the idle countdown in addition to the polling. In case a system resumes from standby this should trigger some action within seconds, as the players trigger this event upon re-connect after resume. In case resume is detected, standby will be prevented, but the countdown be lowered from whatever is set in the prefs (20 mins by default) to three minutes. Any regular player activity within this delay would reset the counter. If there's no activity, the system is allowed to go to sleep after 3 minutes. Looking forward to your testing results :-)
(In reply to comment #67) > Created attachment 7691 [details] > Diff against 7.8 branch adding activity events > > This patch adds a clientactivity event to LMS. This is being used by > PreventStandby to reset the idle countdown in addition to the polling. In > case a system resumes from standby this should trigger some action within > seconds, as the players trigger this event upon re-connect after resume. > > In case resume is detected, standby will be prevented, but the countdown be > lowered from whatever is set in the prefs (20 mins by default) to three > minutes. Any regular player activity within this delay would reset the > counter. If there's no activity, the system is allowed to go to sleep after > 3 minutes. > > Looking forward to your testing results :-) I look forward to testing too - just need guidance please on how to get to the patched version. By applying the diffs? To what? I have the current 7.8 osx download. Not a git user.
Created attachment 7692 [details] .zip file with modified files Please unzip this file in the server folder. It should replace Slim/Control/Request.pm Slim/Player/Client.pm Slim/Plugin/PreventStandby/Plugin.pm Slim/Plugin/PreventStandby/OSX.pm
(In reply to comment #69) > Created attachment 7692 [details] > .zip file with modified files > > Please unzip this file in the server folder. It should replace > > Slim/Control/Request.pm > Slim/Player/Client.pm > Slim/Plugin/PreventStandby/Plugin.pm > Slim/Plugin/PreventStandby/OSX.pm Thanks. Now installed. Seems to be a logic problem somewhere though. I set my allowed idle period to 10 min. Server log is saying: [12-09-10 14:41:24.0019] Slim::Plugin::PreventStandby::Plugin::checkClientActivity (134) Incrementing idle counter. 1 minutes left in allowed idle period. [12-09-10 14:41:24.0022] Slim::Plugin::PreventStandby::Plugin::checkClientActivity (144) Preventing System Standby... [12-09-10 14:42:24.0016] Slim::Plugin::PreventStandby::Plugin::checkClientActivity (149) Players have been idle for 10 minutes. Allowing System Standby... [12-09-10 14:43:24.0019] Slim::Plugin::PreventStandby::Plugin::checkClientActivity (149) Players have been idle for 11 minutes. Allowing System Standby... [12-09-10 14:44:24.0016] Slim::Plugin::PreventStandby::Plugin::checkClientActivity (149) Players have been idle for 12 minutes. Allowing System Standby... [12-09-10 14:45:24.0013] Slim::Plugin::PreventStandby::Plugin::checkClientActivity (149) Players have been idle for 13 minutes. Allowing System Standby... [12-09-10 14:46:24.0012] Slim::Plugin::PreventStandby::Plugin::checkClientActivity (149) Players have been idle for 14 minutes. Allowing System Standby... But pmset -g assertions shows: 10/09/2012 14:45:46 BST Assertion status system-wide: PreventUserIdleDisplaySleep 0 PreventSystemSleep 0 PreventUserIdleSystemSleep 1 ExternalMedia 0 UserIsActive 0 ApplePushServiceTask 0 BackgroundTask 0 Listed by owning process: pid 4070(pmset): [0x00000001000007f0] 00:20:15 NoIdleSleepAssertion named: "pmset prevent sleep" So the pmset is still running. I will stop server and try again.
I had to kill the pmset from the command line after stopping the server. Tried again. Evidence that client activity is being noticed: [12-09-10 15:01:47.0014] Slim::Plugin::PreventStandby::Plugin::checkClientActivity (134) Incrementing idle counter. 5 minutes left in allowed idle period. [12-09-10 15:01:47.0017] Slim::Plugin::PreventStandby::Plugin::checkClientActivity (144) Preventing System Standby... [12-09-10 15:02:42.8303] Slim::Plugin::PreventStandby::Plugin::__ANON__ (107) Client activity was signaled [12-09-10 15:02:42.8306] Slim::Plugin::PreventStandby::Plugin::_playersBusy (177) Player Living Room is busy... [12-09-10 15:02:42.8308] Slim::Plugin::PreventStandby::Plugin::checkClientActivity (127) Resetting idle counter. 10 minutes left in allowed idle period. This was the firmware update for the player (got checksum error on download when server was restarted btw). But then eventually after: [12-09-10 15:28:34.0016] Slim::Plugin::PreventStandby::Plugin::checkClientActivity (134) Incrementing idle counter. 1 minutes left in allowed idle period. [12-09-10 15:28:34.0019] Slim::Plugin::PreventStandby::Plugin::checkClientActivity (144) Preventing System Standby... [12-09-10 15:29:34.0016] Slim::Plugin::PreventStandby::Plugin::checkClientActivity (149) Players have been idle for 10 minutes. Allowing System Standby... [12-09-10 15:30:34.0016] Slim::Plugin::PreventStandby::Plugin::checkClientActivity (149) Players have been idle for 11 minutes. Allowing System Standby... [12-09-10 15:31:34.0012] Slim::Plugin::PreventStandby::Plugin::checkClientActivity (149) Players have been idle for 12 minutes. Allowing System Standby... Got two pmsets still running: Listed by owning process: pid 16276(pmset): [0x000000010000086f] 00:14:53 NoIdleSleepAssertion named: "pmset prevent sleep" pid 6547(pmset): [0x0000000100000853] 00:36:01 NoIdleSleepAssertion named: "pmset prevent sleep" This was because the idle period had expired before I got round to accepting the firmware update - the first pmset was not killed on that expiry. Stopping testing now.
Please remove the ' > /dev/null' in the $command definition in OSX.pm. I added this to suppress the tool's console message, but it messes up the $process object, as it's changing the pid.
(In reply to comment #72) > Please remove the ' > /dev/null' in the $command definition in OSX.pm. I > added this to suppress the tool's console message, but it messes up the > $process object, as it's changing the pid. Strange, but true: pmset now being killed and system sleeps.
The news is good from my testing. On resume, LMS now gets its sleep assertion in, via pmset, *before* the power daemon, powerd, expires its system sleep assertion in 30 sec. Excellent. On resume by something other than player activity, LMS sets its assertion for a relatively short period only. My logs showed 2min 59 sec. Does it need to be this long? Does the 2min relate to your test of resume? On resume by a player (me starting to play something from My Music) the Mac does not go back to sleep after 30sec (because the power assertion gets in in time). It stays awake while playing and goes back to sleep promptly after the idle period times out. So thanks Michael for picking up my suggested approach. I will keep the logs in case they are needed. Now I will try and do my best to understand the code :-) (Wondering why a test needs to be ($idletime && $idletime > 2) for example. Thanks again Roger
Change is committed in 7.8
(In reply to comment #75) > Change is committed in 7.8 DOes that mean I should wait till 7.8 release or so I download the beta now?
If I am reading this right the solution you implemented and back ported to 7.7.3 also affects Windows. If that is the case it is likely to be the reason for servers not sleeping since 7.7.3 reported here: http://forums.slimdevices.com/showthread.php?94898-7-7-2-PC-won-t-go-to-Sleep-anymore&p=756702&viewfull=1#post756702 and here: http://forums.slimdevices.com/showthread.php?99486-Message-on-Touch-Screen-Says-Update-to-7-7-3-r16662&p=757415#post757415