Skip to content

Commit 3991091

Browse files
committed
infuse_iot: database: handle parallel access
Handle parallel access by multiple threads when the offline cache is used. The `shelve` module does not appear to handle this by default. Signed-off-by: Jordan Yates <jordan@embeint.com>
1 parent a2a694d commit 3991091

1 file changed

Lines changed: 10 additions & 2 deletions

File tree

src/infuse_iot/database.py

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44
import binascii
55
import pathlib
66
import shelve
7+
import threading
8+
from contextlib import contextmanager
79

810
from cryptography.hazmat.primitives import serialization
911
from cryptography.hazmat.primitives.asymmetric import x25519
@@ -77,6 +79,7 @@ def __init__(
7779
self._local_root: x25519.X25519PrivateKey | None = None
7880
self._local_root_public: bytes | None = None
7981
self._cache_path = cache_path
82+
self._cache_lock = threading.Lock()
8083
if local_root:
8184
with local_root.open() as f:
8285
private_key = serialization.load_pem_private_key(f.read().encode("utf-8"), password=None)
@@ -130,18 +133,23 @@ def observe_secondary_remote_public_key(self, infuse_id: int, secondary_pub_key:
130133
dev.secondary_device_key_id = binascii.crc32(self._local_root_public + dev.device_public_key) & 0xFFFFFF
131134
dev.local_shared_key = self._local_root.exchange(device_public_key)
132135

136+
@contextmanager
137+
def _with_cache(self):
138+
with self._cache_lock as _lock, shelve.open(str(self._cache_path)) as cache:
139+
yield cache
140+
133141
def _update_cache(self, infuse_id: int, device_pub_key: bytes, shared_key: bytes):
134142
if self._cache_path is None:
135143
return
136144
infuse_id_str = f"{infuse_id:016x}"
137-
with shelve.open(str(self._cache_path)) as cache:
145+
with self._with_cache() as cache:
138146
cache[infuse_id_str] = {"public_key": device_pub_key, "shared_key": shared_key}
139147

140148
def _from_cache(self, infuse_id: int, device_pub_key: bytes) -> bytes | None:
141149
if self._cache_path is None:
142150
return None
143151
infuse_id_str = f"{infuse_id:016x}"
144-
with shelve.open(str(self._cache_path)) as cache:
152+
with self._with_cache() as cache:
145153
state = cache.get(infuse_id_str, None)
146154
if state is None or state["public_key"] != device_pub_key:
147155
return None

0 commit comments

Comments
 (0)