Hot-keys on this page

r m x p   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

#!/usr/bin/env python 

""" 

@file ion/util/timeout.py 

@author David Stuebe 

@brief A timeout decorator method 

""" 

 

from twisted.internet import defer, reactor 

 

from ion.core.exception import IonError 

 

from ion.util import procutils as pu 

 

import ion.util.ionlog 

log = ion.util.ionlog.getLogger(__name__) 

from ion.util.ionlog import  logging 

 

class TimeoutError(IonError): 

    """Raised when time expires in timeout decorator""" 

 

def timeout(secs): 

    """ 

    Decorator to add timeout to Deferred calls 

    https://gist.github.com/735556 

    Credit to theduderog 

    """ 

    def wrap(func): 

        @defer.inlineCallbacks 

        def _timeout(*args, **kwargs): 

 

            if log.getEffectiveLevel() <= logging.DEBUG: 

                s_args = pu.pprint_to_string(args) 

                s_kwargs = pu.pprint_to_string(kwargs) 

                log.debug('Setting Timeout for function "%s" to %f seconds: \nArgs: \n%s\nKWArgs: \n%s' % (func.__name__, secs, s_args, s_kwargs )) 

 

 

            rawD = func(*args, **kwargs) 

            if not isinstance(rawD, defer.Deferred): 

                defer.returnValue(rawD) 

 

            timeoutD = defer.Deferred() 

            timesUp = reactor.callLater(secs, timeoutD.callback, None) 

 

            try: 

                rawResult, timeoutResult = yield defer.DeferredList([rawD, timeoutD], fireOnOneCallback=True, fireOnOneErrback=True, consumeErrors=True) 

            except defer.FirstError, e: 

                #Only rawD should raise an exception 

                assert e.index == 0 

                timesUp.cancel() 

                e.subFailure.raiseException() 

            else: 

                #Timeout 

                if timeoutD.called: 

                    log.debug('Cancelling function callback') 

                    rawD.cancel() 

 

                    if log.getEffectiveLevel() <= logging.INFO:    # only output all this stuff when debugging 

 

                        s_args = pu.pprint_to_string(args) 

                        s_kwargs = pu.pprint_to_string(kwargs) 

                        sep = '*//////////////////////////*\n' 

                        log.error('Timeout error in function "%s"\n%sFunction Args: \n%s\nFunction KWArgs: \n%s %s' % (func.__name__, sep, s_args, s_kwargs, sep )) 

 

                    raise TimeoutError("%s secs have expired in func name %s" % (secs, func.__name__)) 

 

            #No timeout 

            log.debug('Cancelling timeout callback') 

 

            timesUp.cancel() 

            defer.returnValue(rawResult) 

        return _timeout 

    return wrap