gpt4 book ai didi

android - curl_multi_wakeup 似乎没有唤醒关联的 curl_multi_poll - Android(但可能不限于)

转载 作者:行者123 更新时间:2023-12-03 13:26:46 29 4
gpt4 key购买 nike

Curl 版本:7.71.0 带 c-ares
背景
我们正在构建一个集成到移动应用程序中的库。我们的目标是 iOS 和 Android。
curl 初始化发生在库内的静态 block 中。
如果我没记错的话,该库的 iOS 版本被 bundle 到一个框架中,该框架在应用程序启动时加载。
该库的 Android 版本 bundle 在一个模块中,该模块是延迟加载的。 (我知道这是一个问题,特别是因为我们链接到 OpenSSL,但它可能对上下文很重要)。
我们使用 curl 构建了一个小型 HTTP 客户端,允许使用它从受信任的服务器下载一些数据 blob。
快速架构审查
HTTP 客户端在它自己的线程上运行。它拥有 curl_multi_handle ,并且任何开始的传输都附加一个 curl_easy_handle给它,并返回一个句柄到 Response它包含一个缓冲区,用于从中读取接收到的字节,并在需要时用于控制传输。
由于 cURL 句柄不是线程安全的,因此对句柄的任何操作(从现在开始称为任务)都将分派(dispatch)到 HTTP 客户端的线程,并且 boost::shared_future被返回(我们可能想要阻止或不取决于用例)。
以下是主循环结构的粗略概念:

while (!done) {
deal_with_transfer();
check_transfer_status();
cleanup_any_orphan_transfer();
execute_all_queue_tasks();
curl_multi_poll(multi, nullptr, 0, very_large_number, nullptr);
}
追加到任务队列也会执行 curl_multi_wakeup(multi)确保执行该任务(例如,添加新下载也是一个已调度的任务)。
问题
到目前为止,我们只在 Android 上进行了测试,并且我们已经看到在某些情况下,阻塞的 HTTP 客户端任务有时永远不会返回。
日志和堆栈跟踪显示我们等待 HTTP 客户端正在执行的任务,但客户端仍在轮询。一切似乎都表明它在附加任务时没有被唤醒。
我似乎无法在本地设备上复制该问题,但它经常发生足以成为一个阻止问题。
我在这里有点不知所措,我真的不知道从哪里开始寻找重现问题的方法,更不用说修复它了。
我希望我提供了足够的上下文来开始有根据的猜测,甚至找到错误的根源!
谢谢阅读!

最佳答案

后台进程的网络 Activity 限制
与传统的 *nix 操作系统相比,Android 和 iOS 等移动操作系统对后台进程的调度策略不同。移动操作系统倾向于使后台进程饿死以节省电池时间。这被称为 background process optimization并将在应用程序进入后台时应用于应用程序的进程/线程。
从 Android 7 开始,后台进程不再通过 CONNECTIVITY_ACTION 通知网络事件。广播,除非他们在 list 中注册他们想要接收事件。
虽然 lobcurl用于android native code ,从 native 库创建的线程将受应用程序在 list 中声明的​​权利的约束(需要被授予)。
尝试的解决方法
我知道阻塞问题有多令人沮丧,因此我可以为您提供一个快速解决方法,以尝试直到问题得到解决。curl_multi_poll()可以接收在您的代码中设置为 very_large_number 的超时.另外,函数调用的最后一个参数是一个指向整数numfds的指针。将填充 curl_multi_pool() 时发生事件的文件描述符的数量正在汇集。
您可以通过以下方式使用它来构建解决方法:

  • 制作 very_large_number一个 reasonably_small_number
  • 替换nullptr&numfds
  • 环绕curl_multi_polldo ... while循环

  • 所以你会有这样的东西:
    int numfds;
    while (!done) {
    deal_with_transfer();
    check_transfer_status();
    cleanup_any_orphan_transfer();
    execute_all_queue_tasks();
    numfds = 0;
    do {
    curl_multi_poll(multi, nullptr, 0, reasonably_small_number, &numfds);
    numfds += check_for_other_conditions();
    } while ( numfds == 0 );
    }
    选择一个合理的超时时间(例如 1 秒、10 秒、60 秒 ...),这将允许您强制中断池,同时不会耗尽电池。
    我正在添加 check_for_other_conditions()所以你可以使用 is 检查附加条件。以任务队列的大小为例,假设有 curl_multi_poll()的情况可能会错过一个事件,尽管事件发生了,但这个额外的检查可以帮助打破循环并开始执行任务。

    关于android - curl_multi_wakeup 似乎没有唤醒关联的 curl_multi_poll - Android(但可能不限于),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66487631/

    29 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com