RaspyRFM icon indicating copy to clipboard operation
RaspyRFM copied to clipboard

Race condition in `rcpulse.py` sometimes leads to deadlock

Open BenjaminRi opened this issue 1 year ago • 0 comments

The file apps/rcpulse.py is subject to a race condition that sometimes leads to deadlock.

pi@raspberrypi:~/work/RaspyRFM/apps $ python3 rcpulse.py --protocol Foo --id 1234 --repeat 20
RFM69 found on CS 0
Init complete.
^CTraceback (most recent call last):
  File "/home/pi/work/RaspyRFM/apps/rcpulse.py", line 35, in <module>
    rctrx.send(args.protocol, params.__dict__, args.timebase, args.repeats)
  File "/home/pi/work/RaspyRFM/apps/rcprotocols.py", line 1079, in send
    self.__rfmtrx.send(txdata, tb)
  File "/home/pi/work/RaspyRFM/apps/rcprotocols.py", line 1012, in send
    self.__rfmlock.acquire()
KeyboardInterrupt

The root cause seems to be in the class RfmPulseTRX, in particular, the lock __rfmlock is involved. The thread is started in the __init__ function of that class, and the thread is sometimes fast enough to acquire the lock and then block in the __receive function, in particular on the line fifo = self.__rfm.read_fifo_wait(64) (full stack trace below). At that point, it seems like it never relinquishes control of the lock (because the other device only has a receiver and never sends anything). I, on the other hand, would like to send something, which also tries to acquire this lock and blocks forever.

Stack for thread 1966072896
  File "/usr/lib/python3.9/threading.py", line 912, in _bootstrap
    self._bootstrap_inner()
  File "/usr/lib/python3.9/threading.py", line 954, in _bootstrap_inner
    self.run()
  File "/home/pi/work/RaspyRFM/apps/rcprotocols.py", line 959, in run
    self.__receive()
  File "/home/pi/work/RaspyRFM/apps/rcprotocols.py", line 969, in __receive
    fifo = self.__rfm.read_fifo_wait(64)
  File "/home/pi/work/RaspyRFM/raspyrfm/rfm69.py", line 461, in read_fifo_wait
    flags = self.read_reg(RegIrqFlags2)
  File "/home/pi/work/RaspyRFM/raspyrfm/rfmbase.py", line 48, in read_reg
    return int(temp[1])

The result is that nothing is sent, and the utility just hangs forever (or until CTRL+C is pressed).

BenjaminRi avatar Feb 04 '24 21:02 BenjaminRi