Skip to content

Commit

Permalink
solaar: add locks to prevent multiple persisters for device
Browse files Browse the repository at this point in the history
  • Loading branch information
pfps committed Feb 23, 2024
1 parent ecf5e51 commit e03e318
Show file tree
Hide file tree
Showing 2 changed files with 29 additions and 22 deletions.
6 changes: 5 additions & 1 deletion lib/logitech_receiver/device.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ def __init__(self, receiver, number, online, pairing_info=None, handle=None, dev
self._feature_settings_checked = False
self._gestures_lock = _threading.Lock()
self._settings_lock = _threading.Lock()
self._persister_lock = _threading.Lock()
self._notification_handlers = {} # See `add_notification_handler`

if not self.path:
Expand Down Expand Up @@ -105,6 +106,7 @@ def __init__(self, receiver, number, online, pairing_info=None, handle=None, dev
)
if self.number is None: # for direct-connected devices get 'number' from descriptor protocol else use 0xFF
self.number = 0x00 if self.descriptor and self.descriptor.protocol and self.descriptor.protocol < 2.0 else 0xFF
self.ping() # determine whether a direct-connected device is online

if self.descriptor:
self._name = self.descriptor.name
Expand Down Expand Up @@ -306,7 +308,9 @@ def reset(self, no_reply=False):
@property
def persister(self):
if not self._persister:
self._persister = _configuration.persister(self)
with self._persister_lock:
if not self._persister:
self._persister = _configuration.persister(self)
return self._persister

def battery(self): # None or level, next, status, voltage
Expand Down
45 changes: 24 additions & 21 deletions lib/solaar/configuration.py
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ def _device_entry_from_config_dict(data, discard_derived_properties):


save_timer = None
save_lock = threading.Lock()
configuration_lock = threading.Lock()
defer_saves = False # don't allow configuration saves to be deferred


Expand All @@ -140,15 +140,15 @@ def save(defer=False):
if not defer or not defer_saves:
do_save()
else:
with save_lock:
with configuration_lock:
if not save_timer:
save_timer = threading.Timer(5.0, lambda: GLib.idle_add(do_save))
save_timer.start()


def do_save():
global save_timer
with save_lock:
with configuration_lock:
if save_timer:
save_timer.cancel()
save_timer = None
Expand Down Expand Up @@ -239,25 +239,28 @@ def match(wpid, serial, modelId, unitId, c):
modelId and modelId == c.get(_KEY_MODEL_ID) and unitId and unitId == c.get(_KEY_UNIT_ID)
)

if not _config:
_load()
entry = None
modelId = device.modelId if device.modelId != "000000000000" else device.name if device.modelId else None
for c in _config:
if isinstance(c, _DeviceEntry) and match(device.wpid, device.serial, modelId, device.unitId, c):
entry = c
break
if not entry:
if not device.online: # don't create entry for offline devices
with configuration_lock:
if not _config:
_load()
entry = None
# some devices report modelId and unitId as zero so use name and serial for them
modelId = device.modelId if device.modelId != "000000000000" else device._name if device.modelId else None
unitId = device.unitId if device.modelId != "000000000000" else device._serial if device.unitId else None
for c in _config:
if isinstance(c, _DeviceEntry) and match(device.wpid, device._serial, modelId, unitId, c):
entry = c
break
if not entry:
if not device.online: # don't create entry for offline devices
if logger.isEnabledFor(logging.INFO):
logger.info("not setting up persister for offline device %s", device._name)
return
if logger.isEnabledFor(logging.INFO):
logger.info("not setting up persister for offline device %s", device.name)
return
if logger.isEnabledFor(logging.INFO):
logger.info("setting up persister for device %s", device.name)
entry = _DeviceEntry()
_config.append(entry)
entry.update(device.name, device.wpid, device.serial, modelId, device.unitId)
return entry
logger.info("setting up persister for device %s", device.name)
entry = _DeviceEntry()
_config.append(entry)
entry.update(device.name, device.wpid, device.serial, modelId, unitId)
return entry


def attach_to(device):
Expand Down

0 comments on commit e03e318

Please sign in to comment.