Fix trailing references causing memory leak

==== Fixed Issues ====

====  Tech Notes ====
This PR corrects a couple of small issues led to skills being left in memory when.
- Handler for `stop.mycroft` weren't removed from event emitter when
skill shut down. Now is added using `self.add_event()`
- registered intent list `self.events` created a circular reference that
python couldn't resolve a live so this is now deleted at shutdown
- Timers in scheduled skills weren't terminated properly. Now if the
timer is alive it will be joined

====  Documentation Notes ====
Registring event handlers should use `self.add_event` instead of
`self.emitter.on()` To make sure they are cleaned up when skill is
terminated.

==== Localization Notes ====
NONE - point to new strings, language specific functions, etc.

==== Environment Notes ====
NONE - new package requirements, new files being written to disk, etc.

==== Protocol Notes ====
NONE - message types added or changed, new signals, APIs, etc.
pull/1018/head
Åke Forslund 2017-08-25 10:38:14 +02:00
parent 2e479dd453
commit 3be861cee2
2 changed files with 7 additions and 2 deletions

View File

@ -252,7 +252,7 @@ class MycroftSkill(object):
self.stop_time = time.time()
self.stop_threshold = self.config_core.get("skills").get(
'stop_threshold')
self.emitter.on('mycroft.stop', self.__handle_stop)
self.add_event('mycroft.stop', self.__handle_stop, False)
def detach(self):
for (name, intent) in self.registered_intents:
@ -304,7 +304,7 @@ class MycroftSkill(object):
_intent_list = []
_intent_file_list = []
def add_event(self, name, handler, need_self):
def add_event(self, name, handler, need_self=False):
"""
Create event handler for executing intent
@ -518,6 +518,7 @@ class MycroftSkill(object):
# removing events
for e, f in self.events:
self.emitter.remove(e, f)
self.events = None # Remove reference to wrappers
self.emitter.emit(
Message("detach_skill", {"skill_id": str(self.skill_id) + ":"}))

View File

@ -116,7 +116,11 @@ class ScheduledSkill(MycroftSkill):
def shutdown(self):
super(ScheduledSkill, self).shutdown()
# if timer method is running wait for it to complete
self.cancel()
if self.timer and self.timer.isAlive():
self.timer.join()
self.timer = None
class ScheduledCRUDSkill(ScheduledSkill):