fritzy / SleekXMPP

Python 2.6+/3.1+ XMPP Library
http://groups.google.com/group/sleekxmpp-discussion
Other
1.1k stars 299 forks source link

statemachine: wait on from_states does not work properly #154

Closed philipmarivoet closed 12 years ago

philipmarivoet commented 12 years ago

Hi,

The transition_any() method can be told to wait until a specific state is reached before performing the state transition.

This waiting is done using the code at lines 92-100

    while not self.__current_state in from_states:
        # detect timeout:
        remainder = start + wait - time.time()
        if remainder > 0:
            self.notifier.wait(remainder)
        else:
            log.debug("State was not ready")
            self.lock.release()
            return False

The problem will be that at this time the state machine lock is held by the thread running this code, preventing any further state changes to happen.

This is illustrated by the following test program:

#!/usr/bin/env python

from sleekxmpp.thirdparty.statemachine import StateMachine
import threading
import time

sm = StateMachine(['A', 'B', 'C'])

class T(threading.Thread):
    def run(self):
        print "Running"
        time.sleep(10)

        print "Before: A -> B"
        rc = sm.transition('A', 'B')
        print "After: A -> B: ", rc

t = T()
t.start()

print "Before: B -> C"
rc = sm.transition('B', 'C', wait=30)
print "After: B -> C: ", rc

A simple solution is to surround the self.notifier.wait() with release(), acquire()

Better idea might be to use a condition variable instead of an event, this will make it easier to manage the lock.

legastero commented 12 years ago

A condition variable works nicely. Thanks!