【问题标题】:Why am I getting a bps_remove_fd failure when trying to store a QSslSocket inside a QScopedPointer?为什么在尝试将 QSslSocket 存储在 QScopedPointer 中时出现 bps_remove_fd 失败?
【发布时间】:2013-05-14 08:30:06
【问题描述】:

我正在使用 Qt4.8.3 为黑莓剧本开发一个基于网络的应用程序,其中一部分涉及将 QAbstractSocket 存储在 QScopedPointer 中,如下所示:

QScopedPointer<QAbstractSocket> nntp;

在我的实现中,我存储一个 QSslSocket 或一个 QTcpSocket(两者都继承自 QAbstractSocket),具体取决于是否要加密连接,即

if(ssl) {
    nntp.reset(new QSslSocket(this));
    (dynamic_cast<QSslSocket*>(nntp.data())))->connectToHostEncrypted(server, port);
} else {
    nntp.reset(new QTcpSocket(this));
    nntp->connectToHost(server, port);
}

当沿着 ssl 路由(非 ssl 工作正常!)时,我最终会遇到以下运行时错误:

virtual void QEventDispatcherBlackberry::unregisterSocketNotifier(QSocketNotifier*) bps_remove_fd() 失败 19

鉴于错误描述以及代码在其他平台上按预期工作(在 mac 和 linux 上测试)这一事实,该错误可能与黑莓相关。 (注意,数字 19 指的是文件描述符)。

任何想法为什么我会看到此错误以及如何解决它?

谢谢,

本。

编辑:我刚刚意识到,在非 ssl 模式下,我可以只拥有一个 QSslSocket 并将其视为常规 QTcpSocket,而不是使用指针。容易得多。但是,我仍然想知道上述错误的原因

【问题讨论】:

    标签: c++ qt blackberry-10 blackberry-playbook


    【解决方案1】:

    我们可以查看the source code 以了解发生了什么。 unregisterSocketNotifier的源码为:

    void QEventDispatcherBlackberry::unregisterSocketNotifier(QSocketNotifier *notifier)
    {
        // Unregister the fd with bps
        int sockfd = notifier->socket();
        int result = bps_remove_fd(sockfd);
        if (result != BPS_SUCCESS)
            qWarning() << Q_FUNC_INFO << "bps_remove_fd() failed";
    
        // Allow the base Unix implementation to unregister the fd too
        QEventDispatcherUNIX::unregisterSocketNotifier(notifier);
    }
    

    并与bps_remove_fd 文档进行关联,该文档说:

    如果文件描述符存在,它将从通道中删除。 io_handler 回调和相关的用户数据也被移除。

    [returns] BPS_SUCCESS 如果 fd(文件描述符)已成功从通道中删除,BPS_FAILURE 否则设置 errno 值。

    关于导致bps_remove_fd 失败的唯一线索是fd 不存在的可能性,这意味着您的套接字没有任何有效的文件描述符。另一个错误可能是由于未指定的任何原因,文件存在但未删除。

    应该设置变量errno,所以如果你看它,你可能会有更完整的错误描述——虽然我没有尝试,我没有它需要的东西——。

    我打赌 bps_remove_fd 的工作原理与 POSIX 的 close(int fd) 相同,所以我查看了 close's documentation 以了解可能导致失败的原因。它声明它应该/可能在以下情况下失败:

    • 参数不是有效的文件描述符(将失败)。
    • close 可能被信号中断(将失败)。
    • 读取或写入文件系统时出现 I/O 错误(可能失败)。

    我会将此答案作为评论,因为它并没有真正回答您的特定情况下的问题,但我希望它至少可以帮助您进一步了解正在发生的事情:)

    【讨论】:

    • 感谢 Morwenn -- 这真的很全面!正如我在编辑中提到的,我意识到我可以只使用 QSslSocket 并将其视为 QTcpSocket 而不是将 QAbstractPointer 存储在 QScopedPointer 中,然后根据 ssl 要求对其进行重置。这似乎可以缓解上述问题
    猜你喜欢
    • 1970-01-01
    • 2020-06-29
    • 1970-01-01
    • 1970-01-01
    • 2015-07-07
    • 1970-01-01
    • 2013-11-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多