【问题标题】:libmpdclient: detect lost connection to MPD daemonlibmpdclient:检测到 MPD 守护进程的丢失连接
【发布时间】:2015-03-04 15:13:05
【问题描述】:

我正在为我的状态栏编写一个插件来打印 MPD 状态,目前使用libmpdclient 库。在 MPD 重新启动的情况下,它必须能够正确处理丢失的连接,但是在现有的 mpd_connection 对象上使用 mpd_connection_get_error 进行简单检查不起作用——它只能在初始 mpd_connection_new 失败时检测到错误。

这是我正在使用的简化代码:

#include <stdio.h>
#include <unistd.h>
#include <mpd/client.h>

int main(void) {
    struct mpd_connection* m_connection = NULL;
    struct mpd_status* m_status = NULL;
    char* m_state_str;

    m_connection = mpd_connection_new(NULL, 0, 30000);

    while (1) {
        // this check works only on start up (i.e. when mpd_connection_new failed),
        // not when the connection is lost later
        if (mpd_connection_get_error(m_connection) != MPD_ERROR_SUCCESS) {
            fprintf(stderr, "Could not connect to MPD: %s\n", mpd_connection_get_error_message(m_connection));
            mpd_connection_free(m_connection);
            m_connection = NULL;
        }

        m_status = mpd_run_status(m_connection);
        if (mpd_status_get_state(m_status) == MPD_STATE_PLAY) {
            m_state_str = "playing";
        } else if (mpd_status_get_state(m_status) == MPD_STATE_STOP) {
            m_state_str = "stopped";
        } else if (mpd_status_get_state(m_status) == MPD_STATE_PAUSE) {
            m_state_str = "paused";
        } else {
            m_state_str = "unknown";
        }
        printf("MPD state: %s\n", m_state_str);
        sleep(1);
    }
}

当 MPD 在上述程序执行期间停止时,它会出现以下段错误:

Program terminated with signal SIGSEGV, Segmentation fault.
#0  0x00007fb2fd9557e0 in mpd_status_get_state () from /usr/lib/libmpdclient.so.2

我能想到的使程序安全的唯一方法是在每次迭代中建立一个新的连接,这是我希望避免的。但是,如果对libmpdclient 函数的单独调用之间的连接丢失了怎么办?我应该多久检查一次连接,更重要的是如何准确检查连接是否仍然存在?

【问题讨论】:

    标签: c mpd


    【解决方案1】:

    我能找到真正有效的唯一方法(除了重新建立每次运行的连接)是使用idle command。如果mpd_recv_idle(或mpd_run_idle)返回0,这是一个错误情况,您可以将其作为释放连接并从那里运行的提示。 这不是一个完美的解决方案,但它确实可以让您在运行之间保持实时连接,并且可以帮助您避免段错误(尽管我认为您不能完全避免它们,因为如果您发送命令并且 mpd 在您接收之前被杀死它,我很确定图书馆仍然存在段错误)。我不确定是否有更好的解决方案。如果有一种可靠的方法可以通过 API 检测您的连接是否仍然存在,那就太好了,但我找不到任何类似的东西。 libmpdclient 似乎不是为必须处理随时间上升和下降的 mpd 实例而构建的非常长的连接。

    另一个较低级别的选项是使用套接字直接通过its protocol 与 MPD 交互,尽管这样做你可能会重新实现 libmpdclient 本身的大部分内容。

    编辑:不幸的是,idle 命令确实会阻塞,直到发生某些事情,并且只要一个音轨持续存在,它就可以一直阻塞,所以如果你需要你的程序在此期间做其他事情,你必须找到一个异步或在另一个线程中实现它的方法。

    【讨论】:

      【解决方案2】:

      假设“conn”是使用“mpd_connection_new”创建的连接:

      if (mpd_connection_get_error(conn) == MPD_ERROR_CLOSED) {
          // mpd_connection_get_error_message(conn)
          // will return "Connection closed by the server"
      }
      

      您几乎可以在任何 libmpdclient 调用之后运行此检查,包括“mpd_recv_idle”或(根据您的示例)“mpd_run_status”。

      我使用的是 libmpdclient 2.18,这当然对我有用。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-06-14
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多