Hi,
I noticed that an event between modules may get confused in multithread. It
is the following scenarios.
1. The module A sends an event to the module B
2. The module B requires time to process the event...
3. The module A sends an event to the module C
4. The module C returns an answer soon
5. The module A is misunderstanding that It is the response from the module
B (in fact the module C)
I wrote PoC reproducing this issue as follows.
(AppA: the module A)
------------------------------
from ryu.base import app_manager
from ryu.controller.event import EventRequestBase, EventReplyBase
from ryu.lib import hub
class A2BRequest(EventRequestBase):
def __init__(self):
super(A2BRequest, self).__init__()
self.dst = 'AppB'
class A2BReply(EventReplyBase):
def __init__(self, dst):
super(A2BReply, self).__init__(dst)
class A2CRequest(EventRequestBase):
def __init__(self):
super(A2CRequest, self).__init__()
self.dst = 'AppC'
class A2CReply(EventReplyBase):
def __init__(self, dst):
super(A2CReply, self).__init__(dst)
class AppA(app_manager.RyuApp):
def __init__(self, *args, **kwargs):
super(AppA, self).__init__(*args, **kwargs)
# Request in parallel
hub.spawn(self._request_to_b)
hub.spawn(self._request_to_c)
def _request_to_b(self):
request = A2BRequest()
reply = self.send_request(request)
assert isinstance(reply, A2BReply), 'Reply is %s' % reply.__class__
def _request_to_c(self):
request = A2CRequest()
reply = self.send_request(request)
assert isinstance(reply, A2CReply), 'Reply is %s' % reply.__class__
------------------------------
(AppB: the module B)
------------------------------
from ryu.base import app_manager
from ryu.controller.handler import set_ev_cls
from app_a import A2BRequest, A2BReply
import time
class AppB(app_manager.RyuApp):
@set_ev_cls(A2BRequest)
def requst_handler(self, request):
time.sleep(5000) # Take time
reply = A2BReply(request.src)
self.reply_to_request(request, reply)
------------------------------
(AppC: the module C)
------------------------------
from ryu.base import app_manager
from ryu.controller.handler import set_ev_cls
from app_a import A2CRequest, A2CReply
class AppC(app_manager.RyuApp):
@set_ev_cls(A2CRequest)
def requst_handler(self, request):
reply = A2CReply(request.src)
self.reply_to_request(request, reply)
------------------------------
The following result:
------------------------------
loading app ./app_a.py
loading app ./app_b.py
loading app ./app_c.py
loading app ryu.controller.ofp_handler
instantiating app ./app_c.py
instantiating app ./app_b.py
instantiating app ryu.controller.ofp_handler
instantiating app ./app_a.py
hub: uncaught exception: Traceback (most recent call last):
File
"/Users/satoshi/.virtualenvs/ryu32/lib/python2.7/site-packages/ryu/lib/hub.py",
line 48, in _launch
func(*args, **kwargs)
File "/Users/satoshi/Documents/workspace/ryusample/app_a.py", line 43, in
_request_to_b
assert isinstance(reply, A2BReply), 'Reply is %s' % reply.__class__
AssertionError: Reply is <class 'app_a.A2CReply'>
------------------------------
It is A2CReply although it must be A2BReply.
I found that a simple queue is used for the input of an event in
app_manager.RyuApp. It returns as a result what was pushed more early.
IMHO, This becomes a problem when using two or more modules since a module
be made into multithreading in many cases.
Thanks,
Satoshi
------------------------------------------------------------------------------
October Webinars: Code for Performance
Free Intel webinars can help you accelerate application performance.
Explore tips for MPI, OpenMP, advanced profiling, and more. Get the most from
the latest Intel processors and coprocessors. See abstracts and register >
http://pubads.g.doubleclick.net/gampad/clk?id=60134071&iu=/4140/ostg.clktrk
_______________________________________________
Ryu-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/ryu-devel