Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit b55eb25

Browse files
committedMar 18, 2025·
fix: read/write uart decorators can deadlock
feat: introduce _AlvikRLock alvik's read/write uart re-entrant lock
1 parent ea12960 commit b55eb25

File tree

1 file changed

+46
-5
lines changed

1 file changed

+46
-5
lines changed
 

‎arduino_alvik/arduino_alvik.py

Lines changed: 46 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -32,14 +32,55 @@ def wrapper(*args, **kwargs):
3232
return wrapper
3333

3434

35+
class _AlvikRLock:
36+
def __init__(self):
37+
"""Alvik re-entrant Lock implementation"""
38+
self._lock = _thread.allocate_lock()
39+
self._owner = None
40+
self._count = 0
41+
42+
def acquire(self):
43+
tid = _thread.get_ident()
44+
45+
if self._owner == tid:
46+
self._count += 1
47+
return True
48+
49+
self._lock.acquire()
50+
self._owner = tid
51+
self._count = 1
52+
return True
53+
54+
def release(self):
55+
tid = _thread.get_ident()
56+
57+
if self._owner != tid:
58+
raise RuntimeError("Cannot release an unowned lock")
59+
60+
self._count -= 1
61+
if self._count == 0:
62+
self._owner = None
63+
self._lock.release()
64+
65+
def locked(self):
66+
return self._lock.locked()
67+
68+
def __enter__(self):
69+
self.acquire()
70+
return self
71+
72+
def __exit__(self, exc_type, exc_value, traceback):
73+
self.release()
74+
75+
3576
class ArduinoAlvik:
3677
_update_thread_running = False
3778
_update_thread_id = None
3879
_events_thread_running = False
3980
_events_thread_id = None
4081

41-
_write_lock = _thread.allocate_lock()
42-
_read_lock = _thread.allocate_lock()
82+
_write_lock = _AlvikRLock()
83+
_read_lock = _AlvikRLock()
4384

4485
def __new__(cls):
4586
if not hasattr(cls, '_instance'):
@@ -189,13 +230,13 @@ def _idle(self, delay_=1, check_on_thread=False, blocking=False) -> None:
189230
led_val = (led_val + 1) % 2
190231
self.i2c.set_single_thread(False)
191232
if self.is_on():
192-
print("********** Alvik is on **********")
233+
print("\n********** Alvik is on **********")
193234
except KeyboardInterrupt:
194235
self.stop()
195236
sys.exit()
196237
except Exception as e:
197238
pass
198-
print(f'Unable to read SOC: {e}')
239+
print(f'\nUnable to read SOC: {e}')
199240
finally:
200241
LEDR.value(1)
201242
LEDG.value(1)
@@ -252,7 +293,7 @@ def begin(self) -> int:
252293
self.set_behaviour(2)
253294
self._set_color_reference()
254295
if self._has_events_registered():
255-
print('Starting events thread')
296+
print('\n********** Starting events thread **********\n')
256297
self._start_events_thread()
257298
self.set_servo_positions(90, 90)
258299
return 0

0 commit comments

Comments
 (0)
Please sign in to comment.