May be a bug : infinite loop when calling Recorder.block_till_db_ready() at startup

Hi, I’m currently developing a component and I encountered what could be a bug.

The problem is caused by the Recorder component, as explained at the end of the post.


Here is my component (simplified) :

import homeassistant.components.history as history
DEPENDENCIES = ['history']

@asyncio.coroutine
def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
    yield from async_add_devices(
        [HistoryStatsSensor(hass, ... )], True)
    return True

class HistoryStatsSensor(Entity):

    @asyncio.coroutine
    def async_update(self):

        _LOGGER.info(str(start))
        _LOGGER.info(str(end))
        _LOGGER.info(str(self.entity_id))
        history_list = history.state_changes_during_period(start, end, str(self._entity_id))
        _LOGGER.info("DONE")

And here is the problem.
During home assistant boot, the program is just stuck at the history_list line. Here is the log :

INFO:homeassistant.loader:Loaded sensor.history_stats from custom_components.sensor.history_stats
INFO:homeassistant.bootstrap:Setting up sensor
INFO:homeassistant.components.sensor:Setting up sensor.history_stats
INFO:custom_components.sensor.history_stats:2017-01-23 23:00:00+00:00
INFO:custom_components.sensor.history_stats:2017-01-24 07:32:24+00:00
INFO:custom_components.sensor.history_stats:input_boolean.test_button

The program doesn’t exit, it just keeps waiting forever !


UPDATE 1 :
I have found the source of the problem :
History calls recorder.query(), who calls recorder._verify_instance(), who calls recorder.block_till_db_ready()
But block_till_db_ready never stops, it just loops forever.

There is the code :

 def __init__(self, ...) -> None:
    """Initialize the recorder."""
    threading.Thread.__init__(self)
    self.db_ready = threading.Event()

def block_till_db_ready(self):
    """Block until the database session is ready."""
    self.db_ready.wait()

self.db_ready is never set.
How can I solve the problem ?


UPDATE 2 :

I have 2 temporary solutions :

  • calling recorder._INSTANCE._setup_connection() works, but I should not call it myself, that’s not how it is supposed to work.

  • waiting 5 seconds between startup and the first call to history.state_changes_during_period works too, but that is even more dirty.

IS THAT A BUG ?

P.S : Full code is here