从 nodeJS 模块调用时,libspotify 注销崩溃

Posted

技术标签:

【中文标题】从 nodeJS 模块调用时,libspotify 注销崩溃【英文标题】:libspotify logout crashes when called from a nodeJS module 【发布时间】:2013-01-16 00:15:14 【问题描述】:

我正在尝试为包装 libspotify 的 nodeJS 编写一个模块。目标是编写一个 web 应用程序,允许远程控制从 spotify 播放音乐的设备。

我决定按照 spshell 示例来确保线程安全,并用纯 C 语言编写一个“Spotify 服务”,它启动一个调用所有 API 函数的单独线程。

nodeJS 模块然后只调用一些提供的函数来与 spotify 交互。该服务的代码可以在这里找到:http://pastebin.com/KB6uwSC8 新线程在底部启动。

现在,如果我在这样的简单程序中调用它(fget 只是为了有一个简单的方法来完成登录)。我使用 c++ 来尽可能接近 node-gyp 编译代码。

#include <stdio.h>

extern "C" 
        #include "objects/SpotifyService.h"


int  main(int argc, char** argv) 
    login();
    char string[100];
    fgets(string, 100, stdin);
    fprintf(stdout, "Got: %s", string);
    logout();
    fgets(string, 100, stdin);
    fprintf(stdout, "Got: %s", string);
    return 0;

它工作正常。我不能让它崩溃。

如果我在 nodeJS 中使用相同的“服务”(这意味着我只调用 login()logout() 并且什么都不做),它会在退出时崩溃有时,例如 7-8 /10倍。我尝试了很多东西,包括:

将编译器标志从 node-gyp 复制到我的小示例中 摆弄 spotify 线程的线程属性 在 OSX 和 Debian 上编译 使用 libuv 代替普通 pthreads 将我的“服务”编译到共享库并从节点调用它

无济于事。它只是崩溃。从 gdb 中调用时崩溃似乎较少,但这可能是随机的。

来自 gdb 的堆栈跟踪显示如下:

Thread 3 (Thread 0x7ffff65fd700 (LWP 21838)):
#0  0x00007ffff678f746 in ?? () from /usr/local/lib/libspotify.so.12
#1  0x00007ffff6702289 in ?? () from /usr/local/lib/libspotify.so.12
#2  0x00007ffff6702535 in ?? () from /usr/local/lib/libspotify.so.12
#3  0x00007ffff6703b5a in ?? () from /usr/local/lib/libspotify.so.12
#4  0x00007ffff6703c86 in ?? () from /usr/local/lib/libspotify.so.12
#5  0x00007ffff66c5c8b in ?? () from /usr/local/lib/libspotify.so.12
#6  0x00007ffff679a5b3 in sp_session_process_events () from /usr/local/lib/libspotify.so.12
#7  0x00007ffff6aa7839 in spotifyLoop (nervNicht=<value optimized out>) at    ../src/SpotifyService.c:103
#8  0x00007ffff70118ca in start_thread () from /lib/libpthread.so.0
#9  0x00007ffff6d78b6d in clone () from /lib/libc.so.6
#10 0x0000000000000000 in ?? ()

(在 OSX gdb 中显示 libspotify 中调用的函数称为“process_title”。)

由于到目前为止没有任何帮助,我只是不知道我是否可以让它工作,或者它是否是 libspotify 中与 nodeJS 不兼容的东西。我不明白 node-gyp 如何链接 .o 文件,也许有问题?

我在 github 上发现了另外两个尝试这样做的项目,但其中一个将 spotify 主循环实际放在 javascript 中,另一个使用节点 0.1.100 和 libspotify 0.0.4,并且在 2 中没有更新年。我无法从他们两个身上学到任何东西。

【问题讨论】:

【参考方案1】:

好的,我又玩了一些。我只是忽略了注销错误并继续实现其他功能。

我在logged_in 回调中添加了一个新的sp_playlist_container 创建,显然这有所帮助。之后,节点模块不再崩溃(或尚未崩溃)。

static sp_playlistcontainer_callbacks pc_callbacks = 
     .container_loaded = &rootPlaylistContainerLoaded,
;

static void rootPlaylistContainerLoaded(sp_playlistcontainer* pc, void* userdata) 
    int numPlaylists = sp_playlistcontainer_num_playlists(pc);
    fprintf(stdout, "Root playlist synchronized, number of Playlists: %d\n", numPlaylists);


static void loggedIn(sp_session* session, sp_error error) 
    if(SP_ERROR_OK != error) 
            fprintf(stderr, "Error logging in: %s\n", sp_error_message(error));
     else 
            fprintf(stdout, "Service is logged in!\n");
     

    //This is absolutely necessary here, otherwise following callbacks can crash.
    sp_playlistcontainer *pc = sp_session_playlistcontainer(spotifySession);
    sp_playlistcontainer_add_callbacks(pc, &pc_callbacks, NULL);
  

但是 sp_playlist_container 创建必须在logged_in回调中,如果我在另一个函数中调用它(比如,“getPlaylistNames”)程序也会崩溃。

我会看看它是否继续有效,并希望这个答案可以帮助其他人。

【讨论】:

太棒了,只需在登录回调中添加sp_session_playlistcontainer(spotifySession) 即可为我修复崩溃。感谢您分享这个!

以上是关于从 nodeJS 模块调用时,libspotify 注销崩溃的主要内容,如果未能解决你的问题,请参考以下文章

Android 上的 libspotify 从未调用“登录”回调

NodeJS:具有多线程的本机 C++ 模块(openmp)

严格模式更改的规则是啥?

如何使用 libspotify 播放广播

libspotify 导致 Apple App Store 拒绝

无法从 nodejs 模块导出数据库属性