threading.Lock in kodi
#1
Hello everyone,
I have an addon that I use for my own family and that during its execution deletes a file, if it exists, and regenerates it with another content.
The problem is that when adding this addon to the widgets of my skin, this process is executed several times in an asynchronous manner, which leads to errors because different processes want to manipulate the file.

I thought about putting a lock (threading.Lock) in the critical section, but since I don't have access to the main process that launches the widget reload threads, this is not feasible.
I then thought about using a property created in the Home window to do this task: Before entering the critical area, it checks if this property exists, if not, it is created and the instructions on the file are executed. Then the property is deleted again, releasing the "lock". If another process reaches this point and the Home property exists, it waits in a loop until the "lock" is "opened".

This seems to reduce the number of errors, but not completely. Is there a better method to do this?
Reply
#2
That's probably the best way to handle the locking.  I've done that before with an addon I maintain.  The other option is to write a file to the settings directory and then check for its existence.  It achieves the same thing, but the one disadvantage is that the file could survive unexpectedly if Kodi crashes, where as the home property would get reset after a crash.
Reply
#3
Thanks for your reply, but to make sure we are talking about the same thing, let me share a small snippet of my code.

Code:

HOME = xbmcgui.Window(10000)
while HOME.getProperty("Lock") == "closed":
    xbmc.sleep(100)
HOME.setProperty("Lock", "closed")
update() # critical zone
HOME.clearProperty("Lock")

The problem is that checking and assigning ownership are not atomic, and therefore two processes can simultaneously pass through the loop and enter the critical zone.
Reply
#4
Agree with @pkskout. Technically, we are talking here not about a threading lock but an inter-process lock. The only way I can think of is using some object available to all processes - either in-memory (e.g. a Window property) or on a filesystem.

BTW, I'd reather re-write the code snipped above using a context manager.
Reply
#5
I handle this across functions in different Python modules (and between my service module in the addon and the normal addon code) by leveraging a Kodi setting I use as a flag.  It does require a single setting function for all portions of the addon code to read/write from for accessing the Kodi setting and I reset the flag when the addon service starts to ensure the addon starts the same way every time.  I wouldn't suggest this approach for high volume activities but for me it is to handle various database sync process which run every 2, 30, 60 minutes and daily.  It avoids database update collisions.  This approach has been working extremely well for me. 


Thanks,

Jeff
Running with the Mezzmo Kodi addon.  The easier way to share your media with multiple Kodi clients.
Service.autostop , Kodi Selective Cleaner and Mezzmo Kodi addon author.
Reply
#6
(2024-09-29, 10:30)caperucitaferoz Wrote: The problem is that when adding this addon to the widgets of my skin, this process is executed several times in an asynchronous manner, which leads to errors because different processes want to manipulate the file.
I don't understand why multiple instances of your add-on that modifies the file are running. Shouldn't the user have to enter the widget to invoke the add-on?
The reason I'm asking is to see if there isn't a different way to model the problem, like without having to change a shared file at all.
Reply
#7
Good morning and thank you all for your contributions.
 
(2024-09-29, 20:25)jbinkley60 Wrote: I handle this across functions in different Python modules (and between my service module in the addon and the normal addon code) by leveraging a Kodi setting I use as a flag.  
Yes, as @Roman said, the technique is the same, it is based on the use of a resource available for all processes. But it has the same problem, the non-atomicity of the operations.
 
Quote:I don't understand why multiple instances of your add-on that modifies the file are running. Shouldn't the user have to enter the widget to invoke the add-on?
The reason I'm asking is to see if there isn't a different way to model the problem, like without having to change a shared file at all.
No @doko-desuka, widgets are automatically synchronized when starting or stopping a playback. And to get the content of those widgets, each of them invokes the addon with a different path
 
Quote:BTW, I'd reather re-write the code snipped above using a context manager.
I'm not used to using context manager, but I think it refers to something like this. If I'm wrong or you think it can be improved, please feel free to do so. I always learn from the greats!!!

Code:

from contextlib import contextmanager

@contextmanager
def myLock():
    HOME = xbmcgui.Window(10000)
    try:
        while HOME.getProperty("Lock") == "closed":
            xbmc.sleep(100) HOME.setProperty("Lock", "closed")
        yield
    finally:
        HOME.clearProperty("Lock")

with myLock() as lock:
    update() # critical zone
Reply
#8
(2024-09-30, 08:10)caperucitaferoz Wrote: No @doko-desuka, widgets are automatically synchronized when starting or stopping a playback. And to get the content of those widgets, each of them invokes the addon with a different path
Thanks. I'm not used to dynamic list content.

If each widget invokes the same add-on but with different path/parameters, wouldn't this warrant multiple temporary files, one for each variant?
In this case there wouldn't be a race, they each have their own temp file to modify.
Reply

Logout Mark Read Team Forum Stats Members Help
threading.Lock in kodi0