pythongoogle-assist-api

Segmentation fault when freeing up memory assigned to pointer


I am working with the google assistant python library. I believe I have found a bug in the library but the library is now deprecated. I dont really have a choice but to use the library because it allows hotword (i.e. hey google keyword).

AFAIK when they deprecated the api, they didn't provide an alternative implementation that uses the service and provides hotword support.

I think the problem is here:

self._lib.assistant_free(self._inst)

but I don't understand why it crashes because it's clearly has been initialised within the constructor. Also I am using the instance of the class it's holding thoughout the main program.

I can get the segmentation fault to occur when I try adding custom voice commands and when I quit the program which makes alot of sense since the exit function is there for cleanup when the thread is closed.

Stacktrace:

Thread 0xb6f8fb40 (most recent call first):
  File "/home/steven/env/lib/python3.7/site-packages/google/assistant/library/assistant.py", line 119 in __exit__
  File "/home/steven/GassistPi/src/main.py", line 1105 in main
  File "/home/steven/GassistPi/src/main.py", line 1110 in <module>
Segmentation fault

code:

def __init__(self, credentials, device_model_id):
    warnings.warn('Google Assistant Library for Python is deprecated', DeprecationWarning)
    if not device_model_id:
        raise ValueError("device_model_id must be a non-empty string")

    self._event_queue = IterableEventQueue()
    self._load_lib()
    self._credentials_refresher = None
    self._shutdown = False

    self._event_callback = EVENT_CALLBACK(self)
    self._inst = c_void_p(
        self._lib.assistant_new(
            self._event_callback,
            device_model_id.encode('ASCII'), None))
    print(self._inst)
    self._credentials_refresher = CredentialsRefresher(
        credentials, self._set_credentials)
    self._credentials_refresher.start()

def __exit__(self, exception_type, exception_value, traceback):
    """Frees allocated memory belonging to the Assistant."""
    if self._credentials_refresher:
        self._credentials_refresher.stop()
        self._credentials_refresher = None
    self._shutdown = True
    self._lib.assistant_free(self._inst)

Solution

  • You might be calling __exit__() twice, and then trying to free the same pointer multiple times. Check the _shutdown attribute before repeating.

    def __exit__(self, exception_type, exception_value, traceback):
        """Frees allocated memory belonging to the Assistant."""
        if self._shutdown: # Don't do this twice
            return
        if self._credentials_refresher:
            self._credentials_refresher.stop()
            self._credentials_refresher = None
        self._shutdown = True
        self._lib.assistant_free(self._inst)