Python button functions oddly not doing the same
<p>I currently have 2 buttons hooked up to my Raspberry Pi (these are the ones with ring LED's in them) and I'm trying to perform this code</p>

<pre><code>#!/usr/bin/env python
import RPi.GPIO as GPIO
import time

GPIO.setmode(GPIO.BCM)
GPIO.setwarnings(False)
GPIO.setup(17, GPIO.OUT) #green LED
GPIO.setup(18, GPIO.OUT) #red LED
GPIO.setup(4, GPIO.IN, GPIO.PUD_UP) #green button
GPIO.setup(27, GPIO.IN, GPIO.PUD_UP) #red button

def remove_events():
        GPIO.remove_event_detect(4)
        GPIO.remove_event_detect(27)

def add_events():
        GPIO.add_event_detect(4, GPIO.FALLING, callback=green, bouncetime=800)
        GPIO.add_event_detect(27, GPIO.FALLING, callback=red, bouncetime=800)

def red(pin):
        remove_events()
        GPIO.output(17, GPIO.LOW)
        print "red pushed"
        time.sleep(2)
        GPIO.output(17, GPIO.HIGH)
        add_events()

def green(pin):
        remove_events()
        GPIO.output(18, GPIO.LOW)
        print "green pushed"
        time.sleep(2)
        GPIO.output(18, GPIO.HIGH)
        add_events()

def main():
    while True:
        print "waiting"
        time.sleep(0.5)

GPIO.output(17, GPIO.HIGH)
GPIO.output(18, GPIO.HIGH)
GPIO.add_event_detect(4, GPIO.FALLING, callback=green, bouncetime=800)
GPIO.add_event_detect(27, GPIO.FALLING, callback=red, bouncetime=800)

if __name__ == "__main__":
    main()
</code></pre>

<p>On the surface it looks like a fairly easy script. When a button press is detected:</p>

<ol>
<li>remove the events</li>
<li>print the message </li>
<li>wait 2 seconds before adding the events and turning the LED's back on </li>
</ol>

<p>Which normally works out great when I press the green button. I tried it several times in succession and it works without fail. With the red, however, it works well the first time, and the second time, but after it has completed it second red(pin) cycle the script just stops.</p>

<p>Considering both events are fairly similar, I can't explain why it fails on the end of the 2nd red button.</p>

<p><strong>EDIT: I have changed the pins from red and green respectively (either to different pin's completely or swap them). Either way, it's always the red button code (actually now green button) causes an error. So it seems its' not a physical red button problem, nor a pin problem, this just leaves the code to be at fault...</strong></p>

<p>I was able to reproduce your problem on my Raspberry Pi 1, Model B by running your script and connecting a jumper cable between ground and GPIO27 to simulate red button presses.  (Those are pins 25 and 13 on my particular Pi model.)  </p>

<p>The python interpreter is crashing with a Segmentation Fault in the thread dedicated to polling GPIO events after <code>red</code> returns from handling a button press.  After looking at the implementation of the Python <code>GPIO</code> module, it is clear to me that it is unsafe to call <code>remove_event_detect</code> from within an event handler callback, and this is causing the crash.  In particular, removing an event handler while that event handler is currently running can lead to memory corruption, which will result in crashes (as you have seen) or other strange behaviors. </p>

<p>I suspect you are removing and re-adding the event handlers because you are concerned about getting a callback during the time when you are handing a button press.  There is no need to do this.  The GPIO module spins up a single polling thread to monitor GPIO events, and will wait for one callback to return before calling another, regardless of the number of GPIO events you are watching.</p>

<p>I suggest you simply make your calls to <code>add_event_detect</code> as your script starts, and never remove the callbacks.  Simply removing <code>add_events</code> and <code>remove_events</code> (and their invocations) from your script will correct the problem.</p>

<p>If you are interested in the details of the problem in the <code>GPIO</code> module, you can take a look at the <a href="https://pypi.python.org/packages/c1/a8/de92cf6d04376f541ce250de420f4fe7cbb2b32a7128929a600bc89aede5/RPi.GPIO-0.6.2.tar.gz">C source code for that module</a>.  Take a look at <code>run_callbacks</code> and <code>remove_callbacks</code> in the file <code>RPi.GPIO-0.6.2/source/event_gpio.c</code>.  Notice that both of these functions use a global chain of <code>struct callback</code> nodes.  <code>run_callbacks</code> walks the callback chain by grabbing one node, invoking the callback, and then following that node's link to the next callback in the chain.  <code>remove_callbacks</code> will walk the same callback chain, and free the memory associated with the callbacks on a particular GPIO pin.  If <code>remove_callbacks</code> is called in the middle of <code>run_callbacks</code>, the node currently held by <code>run_callbacks</code> can be freed (and have its memory potentially reused and overwritten) before the pointer to the next node is followed.</p>

<p>The reason you see this problem only for the red button is likely due to the order of calls to <code>add_event_detect</code> and <code>remove_event_detect</code> causes the memory previously used by the callback node for the red button to be reclaimed for some other purpose and overwritten earlier than the memory used from the green button callback node is similarly reclaimed.  However, be assured that the problem exists for both buttons -- it is just luck that that the memory associated with the green button callback isn't changed before the pointer to the next callback node is followed.</p>

<p>More generally, there is a concerning lack of thread synchronization around the callback chain use in the GPIO module in general, and I suspect similar problems could occur if <code>remove_event_detect</code> or <code>add_event_detect</code> are called while an event handler is running, even if events are removed from another thread!  I would suggest that the author of the <code>RPi.GPIO</code> module should use some synchronization to ensure that the callback chain can't be modified while callbacks are being made.  (Perhaps, in addition to checking whether the chain is being modified on the polling thread itself, <code>pthread_mutex_lock</code> and <code>pthread_mutex_unlock</code> could be used to prevent other threads from modifying the callback chain while it is in use by the polling thread.)</p>

<p>Unfortunately, that is not currently the case, and for this reason I suggest you avoid calling <code>remove_event_detect</code> entirely if you can avoid it.</p>

python raspberry-pi gpio