3

This is in response to dan's (dan^spotify on IRC) offer to take a look at my testcase, but I post it here in case anyone has encountered similar issues.

I'm experiencing a problem with libspotify where the application crashes (memory access violation) in both of these two scenarios:

  • the first sp_session_process_events (triggered by notify main thread callback) that's called after the sp_session_logout() function is called crashes the application
  • skipping logout and calling sp_session_release() crashes the application

I've applied sufficient synchronization from the session callbacks, and I'm otherwise operating on a single thread.

I've made a small testcase that does the following:

  • Creates session
  • Logs in
  • Waits 10 seconds
  • Attempts to logout, upon which it crashes (when calling sp_session_process_events())
  • If it were successful in logging out (which it isn't), would call sp_session_release()

I made a Gist for the testcase. It can be found here: https://gist.github.com/4496396

The test case is made using Qt (which is what I'm using for my project), so you'd need Qt 5 to compile it. I've also only written it with Windows and Linux in mind (don't have Mac). Assuming you have Qt 5 and Qt Creator installed, the instructions are as follows:

  • Download the gist
  • Copy the libspotify folder into the same folder as the .pro file
  • Copy your appkey.c file into the same folder
  • Edit main.cpp to login with your username and password
  • Edit line 38-39 in sessiontest.cpp and set the cache and settings path to your liking
  • Open up the .pro file and run from Qt Creator

I'd be very grateful if someone could tell me what I'm doing wrong, as I've spent so many hours trying anything I could think of or just staring at it, and I fear I've gone blind to my own mistakes by now.

I've tested it on both Windows 7 and Linux Ubuntu 12.10, and I've found some difference in behavior:

  • On Windows, the testcase crashes invariably regardless of settings and cache paths.
  • On Linux, if setting settings and cache to "" (empty string), logging out and releasing the session works fine.
  • On Linux, if paths are anything else, the first run (when folder does not already exist) logs out and releases session as it should, but on the next run (when folder already exists), it crashes in the exact same way as it does on Windows.

Also, I can report that sp_session_flush_caches() does not cause a crash.

EDIT: Also, hugo___ on IRC was kind enough to test it on OSX for me. He reported no crashes despite running the application several times in a row.

4 Answers4

1

While you very well may be looking at a bug in libspotify, I'd like to point out a possibly redundant call to sp_session_process_events(), from what I gathered from looking at your code.

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);
}

It seems this code will pickup the interval value and start a timer on that to trigger a subsequent call to event(). However, this code will also call startTimer when interval is 0, which is strictly not necessary, or rather means that the app can go about doing other stuff until it gets a notify_main_thread callback. The docs on startTimer says "If interval is 0, then the timer event occurs once every time there are no more window system events to process.". I'm not sure what that means exactly but it seems like it can produce at least one redundant call to sp_session_process_events().

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

henka
  • 109
  • 4
  • You're absolutely right. I did in fact notice this just after posting, and despite changing it to do { sp_session_process_events(m_session, &interval) } while interval == 0 , it seemed to behave in the exact same way. Which is consistent with the fact that I can not recall to have seen interval being 0 when running this testcase (it's printed). Of course, you're right in that this is a mistake on my part, though it does not seem to be the cause, unfortunately.. – Andreas Longva Jan 10 '13 at 18:49
1

I notice that you will get a crash on sp_session_release if you have a track playing when you call it.

griffin2000
  • 709
  • 9
  • 26
0

I have been chasing this issue today. Login/logout works just fine on Mac, but the issue was 100% repeatable as you described on Windows.

By registering empty callbacks for offline_status_updated and credentials_blob_updated, the crash went away. That was a pretty unsatisfying fix, and I wonder if any libspotify developers want to comment on it.

Callbacks registered in my app are:

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

I should explicitly point out that I did not try this on the code you supplied. It would be interesting to know if adding those two extra callbacks works for you. Note that the functions I supply do absolutely nothing. They just have to be there and be registered when you create the session.

paddy
  • 60,864
  • 6
  • 61
  • 103
0

Adding the following call in your "logged in" libspotify callback seems to fix this crash as detailed in this SO post:

sp_session_playlistcontainer(session);

Community
  • 1
  • 1
Frederik
  • 467
  • 6
  • 16