Skip to content
This repository has been archived by the owner on Jan 16, 2024. It is now read-only.

Memory leak between AudioPlayer/ProgressTimer #1128

Closed
2 of 8 tasks
baustinanki opened this issue Dec 14, 2018 · 2 comments
Closed
2 of 8 tasks

Memory leak between AudioPlayer/ProgressTimer #1128

baustinanki opened this issue Dec 14, 2018 · 2 comments

Comments

@baustinanki
Copy link

baustinanki commented Dec 14, 2018

Briefly summarize your issue:

When shutting down audio playback while Alexa is telling me a story (following "Alexa, tell me a story about yourself"), the AudioPlayer instance is not deleted, due to the ProgressTimer it owns still having a shared_ptr reference to it.

What is the expected behavior?

AudioPlayer::doShutdown() should have the effect of removing shared references to itself that it's given to other modules, allowing its deletion.

What behavior are you observing?

AudioPlayer::m_progressTimer holds a shared reference to the AudioPlayer instance that prevents its deletion. The sequence is illustrated by the following log lines.

AudioPlayer receives a play directive in JSON, but it does not have a progressReport section:

[  f] 1 AudioPlayer:handlePlayDirective
[  f] E JsonUtils:findNodeFailed:reason=missingDirectChild,child=progressReport

Thus, the following code in AudioPlayer.cpp sets default interval/delay values:

    rapidjson::Value::ConstMemberIterator progressReport;
    audioItem.stream.progressReport.delay = ProgressTimer::NO_DELAY;
    audioItem.stream.progressReport.interval = ProgressTimer::NO_INTERVAL;
    if (!jsonUtils::findNode(stream->value, "progressReport", &progressReport)) {
        progressReport = stream->value.MemberEnd();
    } else {
        // the code here would set non-default values if they were present, but they aren't

When m_progressTimer.start() is later called upon audio playback beginning, it detects these default values of NO_DELAY/NO_INTERVAL and decides to set its internal state back to IDLE (this code is in ProgressTimer::start():

    if (m_delay != NO_DELAY) {
        if (m_interval != NO_INTERVAL) {
            m_target = std::min(m_delay, m_interval * ((m_offset / m_interval) + 1));
        } else {
            m_target = m_delay;
        }
    } else {
        if (m_interval != NO_INTERVAL) {
            m_target = m_interval * ((m_offset / m_interval) + 1);
        } else {
            ACSDK_DEBUG5(LX("startNotStartingThread").d("reason", "noTarget"));
--->        setState(State::IDLE);
            return;
        }
    }

The debug line there shows up in my log:

[  8] 5 ProgressTimer:startNotStartingThread:reason=noTarget

With the ProgressTimer state now set back to IDLE, the following happens in ProgressTimer::stop():

void ProgressTimer::stop() {
    ACSDK_DEBUG5(LX(__func__));

    // If we are already stopped, there is nothing to do.
    {
        std::lock_guard<std::mutex> stateLock(m_stateMutex);
        if (State::IDLE == m_state) {
--->        return;
        }
    }

This is bad, because it means the m_context shared pointer (back to the AudioPlayer that owns it) does not get reset at the end of the function:

    // ...below above code, from which we've already done an early return

    m_context.reset();
    m_delay = NO_DELAY;
    m_interval = NO_INTERVAL;
    m_target = std::chrono::milliseconds::zero();
}

Thus, the ProgressTimer maintains its shared reference back to the AudioPlayer, preventing its deletion (along with a couple other components the AudioPlayer holds shared references to, like the exception sender and message sender).

Provide the steps to reproduce the issue, if applicable:

  1. Open sample app
  2. Hit t, press [enter]
  3. Say "tell me a story about yourself"
  4. When Alexa replies, hit q then [enter]
  5. Look at log output and observe:
2018-12-14 01:03:30.716 [0] W RequiresShutdown:ShutdownMonitor:reason=never deleted,name=AudioPlayer

This is evidence of the memory leak.

Tell us about your environment:

What version of the AVS Device SDK are you using?

1.10

Tell us what hardware you're using:

  • Desktop / Laptop
  • Raspberry Pi
  • Other - tell us more:

Tell us about your OS (Type & version):

  • Linux
  • MacOS
  • Raspbian Stretch
  • Raspbian Jessy
  • Other - tell us more:
@scotthea-amazon
Copy link
Contributor

Hello baustinanki,

Thank you very much for tracking this down and providing such a clear description of the problem! Your analysis looks correct to us.

Best regards,
-SWH

scotthea-amazon added a commit that referenced this issue Dec 19, 2018
Changes in this update:

**Enhancements**

* Added support for the new Alexa [DoNotDisturb](https://developer.amazon.com/docs/alexa-voice-service/donotdisturb.html) interface, which enables users to toggle the do not disturb (DND) function on their Alexa built-in products.
* The SDK now supports [Opus](https://opus-codec.org/license/) encoding, which is optional. To enable Opus, you must [set the CMake flag to `-DOPUS=ON`](https://github.com/alexa/avs-device-sdk/wiki/Build-Options#Opus-encoding), and include the [libopus library](https://github.com/alexa/avs-device-sdk/wiki/Dependencies#core-dependencies) dependency in your build.
* The MediaPlayer reference implementation has been expanded to support the SAMPLE-AES and AES-128 encryption methods for HLS streaming.
  * AES-128 encryption is dependent on libcrypto, which is part of the required openSSL library, and is enabled by default.
  * To enable [SAMPLE-AES](https://github.com/alexa/avs-device-sdk/wiki/Dependencies#core-dependencies/Enable-SAMPLE-AES-decryption) encryption, you must set the `-DSAMPLE_AES=ON` in your CMake command, and include the [FFMPEG](https://github.com/alexa/avs-device-sdk/wiki/Dependencies#core-dependencies/Enable-SAMPLE-AES-decryption) library dependency in your build.
* A new configuration for [deviceSettings](https://github.com/alexa/avs-device-sdk/blob/v1.11.0/Integration/AlexaClientSDKConfig.json#L59) has been added.This configuration allows you to specify the location of the device settings database.
* Added locale support for es-MX.

**Bug Fixes**

* Fixed an issue where music wouldn't resume playback in the Android app.
* Now all equalizer capabilities are fully disabled when equalizer is turned off in configuration file. Previously, devices were unconditionally required to provide support for equalizer in order to run the SDK.
* [Issue 1106](#1106) - Fixed an issue in which the `CBLAuthDelegate` wasn't using the correct timeout during request refresh.
* [Issue 1128](#1128) - Fixed an issue in which the `AudioPlayer` instance persisted at shutdown, due to a shared dependency with the `ProgressTimer`.
* Fixed in issue that occurred when a connection to streaming content was interrupted, the SDK did not attempt to resume the connection, and appeared to assume that the content had been fully downloaded. This triggered the next track to be played, assuming it was a playlist.
* [Issue 1040](#1040) - Fixed an issue where alarms would continue to play after user barge-in.

**Known Issues**

* `PlaylistParser` and `IterativePlaylistParser` generate two HTTP requests (one to fetch the content type, and one to fetch the audio data) for each audio stream played.
* Music playback history isn't being displayed in the Alexa app for certain account and device types.
* On GCC 8+, issues related to `-Wclass-memaccess` will trigger warnings. However, this won't cause the build to fail, and these warnings can be ignored.
* In order to use Bluetooth source and sink PulseAudio, you must manually load and unload PulseAudio modules after the SDK starts.
* The `ACL` may encounter issues if audio attachments are received but not consumed.
* `SpeechSynthesizerState` currently uses `GAINING_FOCUS` and `LOSING_FOCUS` as a workaround for handling intermediate state. These states may be removed in a future release.
* The Alexa app doesn't always indicate when a device is successfully connected via Bluetooth.
* Connecting a product to streaming media via Bluetooth will sometimes stop media playback within the source application. Resuming playback through the source application or toggling next/previous will correct playback.
* When a source device is streaming silence via Bluetooth, the Alexa app indicates that audio content is streaming.
* The Bluetooth agent assumes that the Bluetooth adapter is always connected to a power source. Disconnecting from a power source during operation is not yet supported.
* On some products, interrupted Bluetooth playback may not resume if other content is locally streamed.
* `make integration` is currently not available for Android. In order to run integration tests on Android, you'll need to manually upload the test binary file along with any input file. At that point, the adb can be used to run the integration tests.
* On Raspberry Pi running Android Things with HDMI output audio, beginning of speech is truncated when Alexa responds to user TTS.
* When the sample app is restarted and network connection is lost, alerts don't play.
* When network connection is lost, lost connection status is not returned via local Text-to Speech (TTS).
@scotthea-amazon
Copy link
Contributor

This is fixed in v1.11. Closing this issue. If you think this issue has been closed in error, please re-open it and include a comment describing why it should not have been closed.

rosspanderson added a commit to anki/avs-device-sdk that referenced this issue Mar 6, 2019
Changes in this update:

**Enhancements**

* Added support for the new Alexa [DoNotDisturb](https://developer.amazon.com/docs/alexa-voice-service/donotdisturb.html) interface, which enables users to toggle the do not disturb (DND) function on their Alexa built-in products.
* The SDK now supports [Opus](https://opus-codec.org/license/) encoding, which is optional. To enable Opus, you must [set the CMake flag to `-DOPUS=ON`](https://github.com/alexa/avs-device-sdk/wiki/Build-Options#Opus-encoding), and include the [libopus library](https://github.com/alexa/avs-device-sdk/wiki/Dependencies#core-dependencies) dependency in your build.
* The MediaPlayer reference implementation has been expanded to support the SAMPLE-AES and AES-128 encryption methods for HLS streaming.
  * AES-128 encryption is dependent on libcrypto, which is part of the required openSSL library, and is enabled by default.
  * To enable [SAMPLE-AES](https://github.com/alexa/avs-device-sdk/wiki/Dependencies#core-dependencies/Enable-SAMPLE-AES-decryption) encryption, you must set the `-DSAMPLE_AES=ON` in your CMake command, and include the [FFMPEG](https://github.com/alexa/avs-device-sdk/wiki/Dependencies#core-dependencies/Enable-SAMPLE-AES-decryption) library dependency in your build.
* A new configuration for [deviceSettings](https://github.com/alexa/avs-device-sdk/blob/v1.11.0/Integration/AlexaClientSDKConfig.json#L59) has been added.This configuration allows you to specify the location of the device settings database.
* Added locale support for es-MX.

**Bug Fixes**

* Fixed an issue where music wouldn't resume playback in the Android app.
* Now all equalizer capabilities are fully disabled when equalizer is turned off in configuration file. Previously, devices were unconditionally required to provide support for equalizer in order to run the SDK.
* [Issue 1106](alexa#1106) - Fixed an issue in which the `CBLAuthDelegate` wasn't using the correct timeout during request refresh.
* [Issue 1128](alexa#1128) - Fixed an issue in which the `AudioPlayer` instance persisted at shutdown, due to a shared dependency with the `ProgressTimer`.
* Fixed in issue that occurred when a connection to streaming content was interrupted, the SDK did not attempt to resume the connection, and appeared to assume that the content had been fully downloaded. This triggered the next track to be played, assuming it was a playlist.
* [Issue 1040](alexa#1040) - Fixed an issue where alarms would continue to play after user barge-in.

**Known Issues**

* `PlaylistParser` and `IterativePlaylistParser` generate two HTTP requests (one to fetch the content type, and one to fetch the audio data) for each audio stream played.
* Music playback history isn't being displayed in the Alexa app for certain account and device types.
* On GCC 8+, issues related to `-Wclass-memaccess` will trigger warnings. However, this won't cause the build to fail, and these warnings can be ignored.
* In order to use Bluetooth source and sink PulseAudio, you must manually load and unload PulseAudio modules after the SDK starts.
* The `ACL` may encounter issues if audio attachments are received but not consumed.
* `SpeechSynthesizerState` currently uses `GAINING_FOCUS` and `LOSING_FOCUS` as a workaround for handling intermediate state. These states may be removed in a future release.
* The Alexa app doesn't always indicate when a device is successfully connected via Bluetooth.
* Connecting a product to streaming media via Bluetooth will sometimes stop media playback within the source application. Resuming playback through the source application or toggling next/previous will correct playback.
* When a source device is streaming silence via Bluetooth, the Alexa app indicates that audio content is streaming.
* The Bluetooth agent assumes that the Bluetooth adapter is always connected to a power source. Disconnecting from a power source during operation is not yet supported.
* On some products, interrupted Bluetooth playback may not resume if other content is locally streamed.
* `make integration` is currently not available for Android. In order to run integration tests on Android, you'll need to manually upload the test binary file along with any input file. At that point, the adb can be used to run the integration tests.
* On Raspberry Pi running Android Things with HDMI output audio, beginning of speech is truncated when Alexa responds to user TTS.
* When the sample app is restarted and network connection is lost, alerts don't play.
* When network connection is lost, lost connection status is not returned via local Text-to Speech (TTS).
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants