【问题标题】:libspotify: logging out or releasing session causes crashlibspotify:注销或释放会话导致崩溃
【发布时间】:2013-01-09 20:55:29
【问题描述】:

这是对 dan (dan^spotify on IRC) 提议查看我的测试用例的回应,但我将其发布在这里,以防有人遇到类似问题。

我在使用 libspotify 时遇到了问题,在这两种情况下应用程序崩溃(内存访问冲突):

  • 在调用 sp_session_logout() 函数后调用的第一个 sp_session_process_events(由通知主线程回调触发)使应用程序崩溃
  • 跳过注销并调用 sp_session_release() 会使应用程序崩溃

我已经从会话回调中应用了足够的同步,否则我在单个线程上操作。

我制作了一个小测试用例,它执行以下操作:

  • 创建会话
  • 登录
  • 等待 10 秒
  • 尝试注销时会崩溃(调用 sp_session_process_events() 时)
  • 如果它成功注销(它不是),将调用 sp_session_release()

我为测试用例做了一个要点。可以在这里找到:https://gist.github.com/4496396

测试用例是使用 Qt 制作的(这是我在项目中使用的),因此您需要 Qt 5 来​​编译它。我也只考虑 Windows 和 Linux 编写它(没有 Mac)。假设您安装了 Qt 5 和 Qt Creator,说明如下:

  • 下载要点
  • 将 libspotify 文件夹复制到与 .pro 文件相同的文件夹中
  • 将 appkey.c 文件复制到同一文件夹中
  • 编辑 main.cpp 以使用您的用户名和密码登录
  • 编辑 sessiontest.cpp 中的第 38-39 行,并根据自己的喜好设置缓存和设置路径
  • 打开 .pro 文件并从 Qt Creator 运行

如果有人能告诉我我做错了什么,我将不胜感激,因为我花了很多时间尝试我能想到的任何事情,或者只是盯着它看,我担心我已经盲目现在我自己的错误。

我已经在 Windows 7 和 Linux Ubuntu 12.10 上对其进行了测试,我发现了一些行为差异:

  • 在 Windows 上,无论设置和缓存路径如何,测试用例都会崩溃。
  • 在 Linux 上,如果将设置和缓存设置为“”(空字符串),注销并释放会话可以正常工作。
  • 在 Linux 上,如果路径是其他任何内容,第一次运行(当文件夹不存在时)会注销并按应有的方式释放会话,但在下一次运行时(当文件夹已经存在时),它会以完全相同的方式崩溃就像在 Windows 上一样。

另外,我可以报告 sp_session_flush_caches() 确实不会导致崩溃。

编辑:另外,IRC 上的 hugo___ 非常友好地为我在 OSX 上进行了测试。尽管连续多次运行该应用程序,但他没有报告任何崩溃。

【问题讨论】:

    标签: spotify


    【解决方案1】:

    虽然您很可能正在查看 libspotify 中的错误,但我想指出对 sp_session_process_events() 的可能冗余调用,这是我从查看您的代码中收集到的。

    void SessionTest::processSpotifyEvents()
    {
      if (m_session == 0)
      {
        qDebug() << "Process: No session.";
        return;
      }
      int interval = 0;
      sp_session_process_events(m_session, &interval);
      qDebug() << interval;
      m_timerId = startTimer(interval);
    }
    

    似乎这段代码将获取interval 值并在其上启动一个计时器以触发对event() 的后续调用。但是,当间隔为 0 时,此代码也会调用 startTimer,这完全没有必要,或者更确切地说,意味着应用程序可以继续执行其他操作,直到它收到 notify_main_thread 回调。 startTimer 上的文档说“如果间隔为 0,那么每次没有更多的窗口系统事件要处理时,计时器事件就会发生一次。”。我不确定这到底是什么意思,但它似乎可以产生至少一个对sp_session_process_events() 的冗余调用。

    http://qt-project.org/doc/qt-4.8/qobject.html#startTimer

    【讨论】:

    • 你说得对。实际上,我在发布后确实注意到了这一点,尽管将其更改为 { sp_session_process_events(m_session, &interval) } while interval == 0 ,但它的行为似乎完全相同。这与我不记得在运行此测试用例(已打印)时看到间隔为 0 的事实是一致的。当然,你是对的,这是我的一个错误,尽管不幸的是,这似乎不是原因..
    【解决方案2】:

    我注意到,如果您在调用 sp_session_release 时正在播放一首曲目,您会在它上崩溃。

    【讨论】:

      【解决方案3】:

      我今天一直在追这个问题。登录/注销在 Mac 上工作得很好,但正如您在 Windows 上描述的那样,问题是 100% 可重复的。

      通过为offline_status_updatedcredentials_blob_updated 注册空回调,崩溃消失了。这是一个非常不令人满意的修复,我想知道是否有任何 libspotify 开发人员想对此发表评论。

      在我的应用中注册的回调是:

      • logged_in
      • logged_out
      • notify_main_thread
      • log_message
      • offline_status_updated
      • credentials_blob_updated

      我应该明确指出我确实没有在您提供的代码上尝试这个。知道添加这两个额外的回调是否适合您会很有趣。请注意,我提供的功能完全没有任何作用。当您创建会话时,他们只需要在那里并进行注册。

      【讨论】:

        【解决方案4】:

        在您的“登录”libspotify 回调中添加以下调用似乎可以修复此崩溃as detailed in this SO post

        sp_session_playlistcontainer(session);

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2011-08-07
          • 2012-02-27
          • 1970-01-01
          • 2013-01-16
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多