Terminating Service on Quit
#1
I'm currently the author for the XBMC Library Auto Update addon. For Eden I changed the type of addon to use the 'xbmc.service' extension.

Everything works pretty well except for when you try to quit XBMC. The service itself is really pretty simple (see code snippet below). It just checks every 60 seconds if it should run the library update or not based on the last time it ran. If the close signal (xbmc.abortRequested) is set then the service exits. The issue is that if you try to close XBMC and there is still say 30 seconds left on the thread sleep operation XBMC will hang for those 30 seconds until the service exits before the program will shut down.

I've been trying to think of a "graceful" way to handle this without having the thread sleep operation reduced needlessly to a small amount of time like 5 or 10 seconds. If anyone has any ideas on how this could be done better please let me know. It isn't a big issue but there must be a way it could be done better. Thanks in advance for any advice.

Code:
while(not xbmc.abortRequested):
            now = time.time()
            
            timer_amounts = {}
            timer_amounts['0'] = 1
            timer_amounts['1'] = 2
            timer_amounts['2'] = 5
            timer_amounts['3'] = 10
            timer_amounts['4'] = 15
            timer_amounts['5'] = 24

            #only do this if we are not playing anything
            if(xbmc.Player().isPlaying() == False and now > self.last_run + (timer_amounts[Addon.getSetting('timer_amount')] * 60 * 60)):
                #run the update since we have just started the program
                if(Addon.getSetting('update_video') == 'true'):
                    xbmc.log('Updating Video')
                    xbmc.executebuiltin('UpdateLibrary(video)')
                if(Addon.getSetting('update_music') == 'true'):
                    xbmc.log('Updating Music')
                    xbmc.executebuiltin('UpdateLibrary(music)')
                    
                #reset the last run timer    
                self.last_run = now
                xbmc.log("Update Library will run again in " + str(timer_amounts[Addon.getSetting("timer_amount")]) + " hours")
                
            #put the thread to sleep for x number of seconds
            time.sleep(60)
Reply
#2
Just for reference.

In the cache plugin we have to constantly accept connections, but without using a sleep function the cpu went to 100% constantly(obviously). So we currently have it at time.sleep(0.5).

Slower than that would make the cache loose it's purpose(be fast), but 0.5s didn't seem to have much impact on overal CPU usage. At least on my systems.

I'm not saying that having a lot of services running with time.sleep(0.5) is a good idea, a better solution would certainly be welcome.
Reply
#3
I have set sleep on 10 seconds.
Read/follow the forum rules.
For troubleshooting and bug reporting, read this first
Interested in seeing some YouTube videos about Kodi? Go here and subscribe
Reply
#4
thanks for the comments.

@TobiasTheCommie - you had my concerns right on. I didn't want to waste a bunch of CPU checking for this, but glad to know you didn't see anything really detrimental with having such a quick check time.

I ended up going with a 10 second wait time on the version I asked to be added to the pre-Eden repo. Still a little long when waiting for XBMC to exit, but I don't really like the idea of a simple library updater needing to constantly run either. For as often as I close XBMC 10 seconds or less is fine with me.
Reply
#5
To reduce the cpu load, but still get a reasonably fast response time for xbmc.abortRequested you could use a short sleep time and add a counter so the complex code only runs every ie. 60 loops.

Code:
loopCount = 0
while not xbmc.abortRequested:
    time.sleep( 0.5 ) #Half second response time to abortRequested
    loopCount += 1
    if loopCount >= 120: # 0.5 * 120 = 60 seconds
        loopCount = 0
        #Your complex code here

Instead of a counter, you could also choose to store the time at which the loop should run and compare against that.

Code:
DELAY = 60
nextLoop = time.time() + DELAY
while not xbmc.abortRequested:
    time.sleep(0.5)
    now = time.time()
    if now >= nextLoop:
        nextLoop = now + DELAY
        #Complex code here

This is code is likely slightly less CPU efficient (though negligible at 0.5Hz), but it lets you easily adjust the two delays independently of each other. By calculating the next time just after the sleep, it also removes any additional delay added by the execution time of the complex code block (as long as the complex code can execute fully within the defined delay) giving a more accurate start to start time.
Reply

Logout Mark Read Team Forum Stats Members Help
Terminating Service on Quit0