Skip to content

Commit

Permalink
Bugfix mqtt socket memory error (home-assistant#6501)
Browse files Browse the repository at this point in the history
* Bugfix mqtt socket memory error

* Fix tests

* Fix lint
  • Loading branch information
pvizeli authored and balloob committed Mar 9, 2017
1 parent 855756c commit 20fcd1f
Show file tree
Hide file tree
Showing 3 changed files with 15 additions and 34 deletions.
32 changes: 9 additions & 23 deletions homeassistant/components/mqtt/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@
from homeassistant.util.async import (
run_coroutine_threadsafe, run_callback_threadsafe)
from homeassistant.const import (
EVENT_HOMEASSISTANT_START, EVENT_HOMEASSISTANT_STOP, CONF_VALUE_TEMPLATE,
CONF_USERNAME, CONF_PASSWORD, CONF_PORT, CONF_PROTOCOL, CONF_PAYLOAD)
EVENT_HOMEASSISTANT_STOP, CONF_VALUE_TEMPLATE, CONF_USERNAME,
CONF_PASSWORD, CONF_PORT, CONF_PROTOCOL, CONF_PAYLOAD)
from homeassistant.components.mqtt.server import HBMQTT_CONFIG_SCHEMA

_LOGGER = logging.getLogger(__name__)
Expand Down Expand Up @@ -331,18 +331,11 @@ def async_setup(hass, config):
@asyncio.coroutine
def async_stop_mqtt(event):
"""Stop MQTT component."""
yield from hass.data[DATA_MQTT].async_stop()
yield from hass.data[DATA_MQTT].async_disconnect()

@asyncio.coroutine
def async_start_mqtt(event):
"""Launch MQTT component when Home Assistant starts up."""
yield from hass.data[DATA_MQTT].async_start()
hass.bus.async_listen_once(EVENT_HOMEASSISTANT_STOP, async_stop_mqtt)

hass.bus.async_listen_once(EVENT_HOMEASSISTANT_START, async_start_mqtt)
hass.bus.async_listen_once(EVENT_HOMEASSISTANT_STOP, async_stop_mqtt)

success = yield from hass.data[DATA_MQTT].async_connect()

if not success:
return False

Expand Down Expand Up @@ -442,31 +435,25 @@ def async_publish(self, topic, payload, qos, retain):
with (yield from self._paho_lock):
yield from self.hass.loop.run_in_executor(
None, self._mqttc.publish, topic, payload, qos, retain)
yield from asyncio.sleep(0, loop=self.hass.loop)

@asyncio.coroutine
def async_connect(self):
"""Connect to the host. Does not process messages yet.
"""Connect to the host. Does process messages yet.
This method must be run in the event loop and returns a coroutine.
This method is a coroutine.
"""
result = yield from self.hass.loop.run_in_executor(
None, self._mqttc.connect, self.broker, self.port, self.keepalive)

if result != 0:
import paho.mqtt.client as mqtt
_LOGGER.error('Failed to connect: %s', mqtt.error_string(result))
else:
self._mqttc.loop_start()

return not result

def async_start(self):
"""Run the MQTT client.
This method must be run in the event loop and returns a coroutine.
"""
return self.hass.loop.run_in_executor(None, self._mqttc.loop_start)

def async_stop(self):
def async_disconnect(self):
"""Stop the MQTT client.
This method must be run in the event loop and returns a coroutine.
Expand All @@ -493,7 +480,6 @@ def async_subscribe(self, topic, qos):

result, mid = yield from self.hass.loop.run_in_executor(
None, self._mqttc.subscribe, topic, qos)
yield from asyncio.sleep(0, loop=self.hass.loop)

_raise_on_error(result)
self.progress[mid] = topic
Expand Down
2 changes: 1 addition & 1 deletion homeassistant/helpers/dispatcher.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ def async_remove_dispatcher():

def dispatcher_send(hass, signal, *args):
"""Send signal and data."""
hass.add_job(async_dispatcher_send, hass, signal, *args)
hass.loop.call_soon_threadsafe(async_dispatcher_send, hass, signal, *args)


@callback
Expand Down
15 changes: 5 additions & 10 deletions tests/components/mqtt/test_init.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,7 @@
from homeassistant.setup import setup_component, async_setup_component
import homeassistant.components.mqtt as mqtt
from homeassistant.const import (
EVENT_CALL_SERVICE, ATTR_DOMAIN, ATTR_SERVICE, EVENT_HOMEASSISTANT_START,
EVENT_HOMEASSISTANT_STOP)
EVENT_CALL_SERVICE, ATTR_DOMAIN, ATTR_SERVICE, EVENT_HOMEASSISTANT_STOP)
from homeassistant.helpers.dispatcher import async_dispatcher_connect

from tests.common import (
Expand Down Expand Up @@ -55,19 +54,15 @@ def record_calls(self, *args):
"""Helper for recording calls."""
self.calls.append(args)

def test_client_starts_on_home_assistant_start(self):
""""Test if client start on HA launch."""
self.hass.bus.fire(EVENT_HOMEASSISTANT_START)
self.hass.block_till_done()
self.assertTrue(self.hass.data['mqtt'].async_start.called)
def test_client_starts_on_home_assistant_mqtt_setup(self):
"""Test if client is connect after mqtt init on bootstrap."""
assert self.hass.data['mqtt'].async_connect.called

def test_client_stops_on_home_assistant_start(self):
"""Test if client stops on HA launch."""
self.hass.bus.fire(EVENT_HOMEASSISTANT_START)
self.hass.block_till_done()
self.hass.bus.fire(EVENT_HOMEASSISTANT_STOP)
self.hass.block_till_done()
self.assertTrue(self.hass.data['mqtt'].async_stop.called)
self.assertTrue(self.hass.data['mqtt'].async_disconnect.called)

def test_publish_calls_service(self):
"""Test the publishing of call to services."""
Expand Down

0 comments on commit 20fcd1f

Please sign in to comment.