{"action":"created","issue":{"url":"https://api.github.com/repos/RPi-Distro/python-gpiozero/issues/50","labels_url":"https://api.github.com/repos/RPi-Distro/python-gpiozero/issues/50/labels{/name}","comments_url":"https://api.github.com/repos/RPi-Distro/python-gpiozero/issues/50/comments","events_url":"https://api.github.com/repos/RPi-Distro/python-gpiozero/issues/50/events","html_url":"https://github.com/RPi-Distro/python-gpiozero/issues/50","id":110201338,"number":50,"title":"Heisenbug in add_event_detect","user":{"login":"waveform80","id":1076190,"avatar_url":"https://avatars.githubusercontent.com/u/1076190?v=3","gravatar_id":"","url":"https://api.github.com/users/waveform80","html_url":"https://github.com/waveform80","followers_url":"https://api.github.com/users/waveform80/followers","following_url":"https://api.github.com/users/waveform80/following{/other_user}","gists_url":"https://api.github.com/users/waveform80/gists{/gist_id}","starred_url":"https://api.github.com/users/waveform80/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/waveform80/subscriptions","organizations_url":"https://api.github.com/users/waveform80/orgs","repos_url":"https://api.github.com/users/waveform80/repos","events_url":"https://api.github.com/users/waveform80/events{/privacy}","received_events_url":"https://api.github.com/users/waveform80/received_events","type":"User","site_admin":false},"labels":[{"url":"https://api.github.com/repos/RPi-Distro/python-gpiozero/labels/bug","name":"bug","color":"fc2929"}],"state":"open","locked":false,"assignee":{"login":"waveform80","id":1076190,"avatar_url":"https://avatars.githubusercontent.com/u/1076190?v=3","gravatar_id":"","url":"https://api.github.com/users/waveform80","html_url":"https://github.com/waveform80","followers_url":"https://api.github.com/users/waveform80/followers","following_url":"https://api.github.com/users/waveform80/following{/other_user}","gists_url":"https://api.github.com/users/waveform80/gists{/gist_id}","starred_url":"https://api.github.com/users/waveform80/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/waveform80/subscriptions","organizations_url":"https://api.github.com/users/waveform80/orgs","repos_url":"https://api.github.com/users/waveform80/repos","events_url":"https://api.github.com/users/waveform80/events{/privacy}","received_events_url":"https://api.github.com/users/waveform80/received_events","type":"User","site_admin":false},"milestone":null,"comments":9,"created_at":"2015-10-07T11:06:59Z","updated_at":"2015-11-16T21:25:38Z","closed_at":null,"body":"The one issue I've come across in practice with RPi.GPIO (which annoyingly happened during the demo too the other day!) is that sometimes (not often - it's a Heisenbug) the library fails to add edge detection when requested. It happens particularly with Button and LightSensor which both use `add_event_detect`. I haven't yet tied down if there's any pre-requisites to re-produce but it's something I need to look into as when it manifests the only option is to shut down the interpreter and try again.\r\n\r\nSo, first step: mitigation. Ensure all resources allocated in all constructors are cleaned up in the event the constructor fails (in particular cleaning up the allocation of the GPIO pin and pull-up). Second step: dig into the C source code and find out what on earth is causing `add_event_detect` to actually fail on rare occasions. I'm leaving this as the second step as it's going to be Hard (tm); probably some subtle race condition or something like that."},"comment":{"url":"https://api.github.com/repos/RPi-Distro/python-gpiozero/issues/comments/157175502","html_url":"https://github.com/RPi-Distro/python-gpiozero/issues/50#issuecomment-157175502","issue_url":"https://api.github.com/repos/RPi-Distro/python-gpiozero/issues/50","id":157175502,"user":{"login":"waveform80","id":1076190,"avatar_url":"https://avatars.githubusercontent.com/u/1076190?v=3","gravatar_id":"","url":"https://api.github.com/users/waveform80","html_url":"https://github.com/waveform80","followers_url":"https://api.github.com/users/waveform80/followers","following_url":"https://api.github.com/users/waveform80/following{/other_user}","gists_url":"https://api.github.com/users/waveform80/gists{/gist_id}","starred_url":"https://api.github.com/users/waveform80/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/waveform80/subscriptions","organizations_url":"https://api.github.com/users/waveform80/orgs","repos_url":"https://api.github.com/users/waveform80/repos","events_url":"https://api.github.com/users/waveform80/events{/privacy}","received_events_url":"https://api.github.com/users/waveform80/received_events","type":"User","site_admin":false},"created_at":"2015-11-16T21:25:38Z","updated_at":"2015-11-16T21:25:38Z","body":"Notes for my reference:\r\n\r\n* After patching RPi.GPIO to return unique error conditions for several scenarios I've tracked down two causes of this issue (so there's a couple of things to fix here - but I'm not sure about the root causes yet so I'm not sure how hard either is yet)\r\n* One cause is a leak in RPi.GPIO's thread handling. The event thread is stopped and started as necessary, but the thread only calls `pthread_exit`. To clean up the thread's resources it's necessary to call `pthread_join` from another thread *after* the thread has been cancelled or exited. This mean that if one repeatedly starts and stops event detection one can pretty quickly exhaust the available resources and the pthread_create call returns EAGAIN (which isn't retried and is treated as a permanent error - although that's probably reasonable in the circumstances).\r\n* Another cause is a race condition somewhere in the chain of calls under `new_gpio`. I haven't tracked down the root cause here but my gut instinct is that it's either something to do with the arbitrary delay in `gpio_export` or the lack of locking on gpio_list. `new_gpio` mutates it and `poll_thread` in a background thread enumerates it; neither uses mutexes so it's possible there's a nasty race condition here. Although if that's the case I'd expect a segfault rather than the error we're seeing (that said I've seen an unexplained segfault in gpiozero on one occasion so maybe this occurs but extremely rarely)."}}