Menu

#202 Make adding and removing event handlers (add_event_detect and remove_event_detect) thread safe.

New
nobody
None
Critical
Patch
2022-09-25
2022-02-13
Wout
No

Python crashes when adding/removing event handlers while inside the callback (the crash happens just after the callback completes). This is a known/very old problem apparently, from 5 years ago: https://stackoverflow.com/questions/39785577/python-button-functions-oddly-not-doing-the-same). It would be great if the callback handling would become thread safe.

The use case is for example a button matrix. A call back wakes up the program once a button is pressed. But inside the callback you need to turn off and on pins many times to find out which button is pressed, resulting in an avalanche of callbacks. It would be great to be able to temporarily disable the callbacks for the pins involved in the button matrix.

What I'm doing now as a workaround is set a bouncetime in GPIO.add_event_detect, but it feels dirty, and also I'm still getting some random callbacks after the original callback, so it doesn't seem to be 100% reliable.

Discussion

  • Wout

    Wout - 2022-02-14

    Looking at the code, it can be 99% be resolved by a small modification to run_py_callbacks(unsigned int gpio) by moving the code inside the if (cb->gpio == gpio) branch outside the loop, this would allow the callback to modify the callback linked list without crashing the loop.

    This would leave still a tiny chance of the callback getting called during the initial setup of the callbacks, getting into a race condition if I'm right, but I haven't looked at how the threading is set up yet. So a lock might still be needed, but the change above would mostly resolve it.

    I can play with the code the coming week.

     
  • Wout

    Wout - 2022-02-14

    I've made the modifications to allow callbacks adding/removing callbacks, see attached files. I've moved performing the call backs to outside the loop, so the callback doesn't mess up the loop. Plus I've added a mutex so another thread cannot mess up the loop if the other thread is adding/removing callbacks.

    There's only one tiny risk during startup, since the polling thread is created/started when adding the first callback, in theory when that callback is called right away, it can add callbacks, while the main thread is also still busy adding callbacks. It would be nice to be able to explicitly start the polling thread after all the call backs have been added to get into a consistent state.

     

Log in to post a comment.

Want the latest updates on software, tech news, and AI?
Get latest updates about software, tech news, and AI from SourceForge directly in your inbox once a month.