base/app_manager: RyuApp initialization race at startup

There is a race between RyuApp instantiation and starting its thread.
Each RyuApp spawns an event-loop thread which handles events and may
generate events when a RyuApp instance is created.
Currently on startup, necessary RyuApps are created, and event-loop
thread is created at the same time. Then event-piping (which events are
delivered to which RyuApp) is done. This causes missing events if
RyuApp which was create early generates events before finishing event-piping.

To address it, split RyuApp startup into three phases from two phase.
- create RyuApp instances
- event piping
- then, start event-loop threads.

Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
Signed-off-by: YAMAMOTO Takashi <yamamoto@valinux.co.jp>
Signed-off-by: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>
This commit is contained in:
Isaku Yamahata 2013-11-22 16:45:57 +09:00 committed by FUJITA Tomonori
parent b7235b395a
commit 5dd45aea0c
2 changed files with 18 additions and 0 deletions

View File

@ -400,6 +400,16 @@ class GRETunnel(app_manager.RyuApp):
[dpset.EventDP, PortSet.EventTunnelKeyDel, PortSet.EventVMPort,
PortSet.EventTunnelPort, ofp_event.EventOFPPacketIn])
def start(self):
super(GRETunnel, self).start()
self.port_set.start()
def stop(self):
app_mgr = app_manager.get_instance()
app_mgr.uninstantiate(self.port_set)
self.port_set = None
super(GRETunnel, self).stop()
# TODO: track active vm/tunnel ports
@handler.set_ev_handler(dpset.EventDP)

View File

@ -64,6 +64,11 @@ class RyuApp(object):
self.events = hub.Queue(128)
self.replies = hub.Queue()
self.logger = logging.getLogger(self.name)
def start(self):
"""
Hook that is called after startup initialization is done.
"""
self.threads.append(hub.spawn(self._event_loop))
def register_handler(self, ev_cls, handler):
@ -240,6 +245,9 @@ class AppManager(object):
for ev_cls in i.event_handlers.keys():
LOG.debug(" CONSUMES %s" % (ev_cls.__name__,))
for app in self.applications.values():
app.start()
def close(self):
def close_all(close_dict):
for app in close_dict.values():