[pytango] 19/26: Fix SF bug #747: event callback gets called in tango thread in gevent mode

Sandor Bodo-Merle sbodomerle-guest at moszumanska.debian.org
Thu Sep 28 19:16:14 UTC 2017


This is an automated email from the git hooks/post-receive script.

sbodomerle-guest pushed a commit to annotated tag v8.1.8
in repository pytango.

commit 0000172d9f190e3dddd0dcf7357a34f7fbd3a62d
Author: Jose Tiago Coutinho Macara <coutinho at esrf.fr>
Date:   Wed Oct 21 17:10:44 2015 +0200

    Fix SF bug #747: event callback gets called in tango thread in gevent mode
    
    - Create an event_loop greenlet. Callback code is transferred to this
      greenlet for execution
    - Increase PyTango patch version number since this introduces a difference
      in behavior
---
 src/boost/python/device_proxy.py |  9 ++++++---
 src/boost/python/green.py        | 26 +++++++++++++++++++++++++-
 src/boost/python/release.py      |  2 +-
 src/boost/python/tango_gevent.py | 28 +++++++++++++++++++++++++++-
 4 files changed, 59 insertions(+), 6 deletions(-)

diff --git a/src/boost/python/device_proxy.py b/src/boost/python/device_proxy.py
index 8b8206d..bd43fb7 100644
--- a/src/boost/python/device_proxy.py
+++ b/src/boost/python/device_proxy.py
@@ -32,7 +32,7 @@ from .utils import is_pure_str, is_non_str_seq, is_integer
 from .utils import seq_2_StdStringVector, StdStringVector_2_seq
 from .utils import seq_2_DbData, DbData_2_dict
 from .utils import document_method as __document_method
-from .green import result, submit, green, get_green_mode
+from .green import result, submit, green, green_cb, get_green_mode, get_event_loop
 
 _UNSUBSCRIBE_LIFETIME = 60
 
@@ -96,6 +96,9 @@ def get_device_proxy(*args, **kwargs):
     wait = kwargs.pop('wait', True)
     timeout = kwargs.pop('timeout', None)
 
+    # make sure the event loop is initialized
+    get_event_loop(green_mode)
+
     d = submit(green_mode, DeviceProxy, *args, **kwargs)
     return result(d, green_mode, wait=wait, timeout=timeout)
 
@@ -837,10 +840,10 @@ def __DeviceProxy__subscribe_event (self, attr_name, event_type, cb_or_queuesize
 
     if isinstance(cb_or_queuesize, collections.Callable):
         cb = __CallBackPushEvent()
-        cb.push_event = cb_or_queuesize
+        cb.push_event = green_cb(cb_or_queuesize, self.get_green_mode())
     elif hasattr(cb_or_queuesize, "push_event") and isinstance(cb_or_queuesize.push_event, collections.Callable):
         cb = __CallBackPushEvent()
-        cb.push_event = cb_or_queuesize.push_event
+        cb.push_event = green_cb(cb_or_queuesize.push_event, self.get_green_mode())
     elif is_integer(cb_or_queuesize):
         cb = cb_or_queuesize  # queuesize
     else:
diff --git a/src/boost/python/green.py b/src/boost/python/green.py
index c36c2ff..a0ec36f 100644
--- a/src/boost/python/green.py
+++ b/src/boost/python/green.py
@@ -14,7 +14,8 @@ __all__ = ["get_green_mode", "set_green_mode",
            "get_synch_executor", "synch_submit",
            "get_gevent_executor", "gevent_submit",
            "get_futures_executor", "futures_submit",
-           "result", "submitable", "green"] 
+           "get_event_loop", "get_gevent_event_loop",
+           "result", "submitable", "green", "green_cb"]
 
 __docformat__ = "restructuredtext"
 
@@ -24,6 +25,7 @@ from functools import wraps
 from ._PyTango import GreenMode
 from .tango_gevent import get_global_executor as get_gevent_executor
 from .tango_gevent import submit as gevent_submit
+from .tango_gevent import get_event_loop as get_gevent_event_loop
 from .tango_futures import get_global_executor as get_futures_executor
 from .tango_futures import submit as futures_submit
 
@@ -92,6 +94,10 @@ __submit_map = {
     GreenMode.Gevent:      gevent_submit,
 }
 
+__event_loop_map = {
+    GreenMode.Gevent:      get_gevent_event_loop,
+}
+
 def get_executor(mode):
     return __executor_map[mode]()
 
@@ -103,6 +109,11 @@ def submit(mode, fn, *args, **kwargs):
 
 spawn = submit
 
+def get_event_loop(mode):
+    f = __event_loop_map.get(mode)
+    if f:
+        return f()
+
 def result(value, green_mode, wait=True, timeout=None):
     if wait and not green_mode is GreenMode.Synchronous:
         if green_mode == GreenMode.Futures:
@@ -165,3 +176,16 @@ def green(fn):
         return result(ret, green_mode, wait=wait, timeout=timeout)
     return greener     
 
+def green_cb(fn, green_mode=None):
+    """return a green verion of the given callback."""
+
+    @wraps(fn)
+    def greener(*args, **kwargs):
+        event_loop = get_event_loop(green_mode)
+        if event_loop is None:
+            fn(*args, **kwargs)
+        else:
+            event_loop.submit(fn, *args, **kwargs)
+
+    return greener
+
diff --git a/src/boost/python/release.py b/src/boost/python/release.py
index b13d7ff..4c9d904 100644
--- a/src/boost/python/release.py
+++ b/src/boost/python/release.py
@@ -40,7 +40,7 @@ class Release:
             - keywords : (seq<str>) list of keywords
             - license : (str) the license"""
     name = 'PyTango'
-    version_info = (8, 1, 7, 'dev', 0)
+    version_info = (8, 1, 8, 'dev', 0)
     version = '.'.join(map(str, version_info[:3]))
     version_long = version + ''.join(map(str, version_info[3:]))
     version_description = 'This version implements the C++ Tango 8.1 API.'
diff --git a/src/boost/python/tango_gevent.py b/src/boost/python/tango_gevent.py
index 60919eb..4fa6a6e 100644
--- a/src/boost/python/tango_gevent.py
+++ b/src/boost/python/tango_gevent.py
@@ -13,7 +13,8 @@ from __future__ import absolute_import
 import sys
 import types
 
-__all__ = ["get_global_threadpool", "get_global_executor", "submit", "spawn"]
+__all__ = ["get_global_threadpool", "get_global_executor",
+           "get_event_loop", "submit", "spawn"]
 
 def get_global_threadpool():
     import gevent
@@ -67,3 +68,28 @@ def spawn(fn, *args, **kwargs):
 get_global_executor = get_global_threadpool
 
 submit = spawn
+
+__event_loop = None
+
+def get_event_loop():
+    global __event_loop
+    if __event_loop is None:
+        import gevent
+        import gevent.queue
+
+        def loop(queue):
+            while True:
+                event = queue.get()
+                f, args, kwargs = event
+                try:
+                    f(*args, **kwargs)
+                except Exception as e:
+                    sys.excepthook(*sys.exc_info())
+
+        def submit(fn, *args, **kwargs):
+            queue.put((fn, args, kwargs))
+
+        queue = gevent.queue.Queue()
+        __event_loop = gevent.spawn(loop, queue)
+        __event_loop.submit = submit
+    return __event_loop

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/debian-science/packages/pytango.git



More information about the debian-science-commits mailing list