Pul*_*ulo 9 c c++ android curl
卷曲版本:7.71.0 带 c-ares
我们正在构建一个集成到移动应用程序中的库。我们同时针对 iOS 和 Android。Curl 初始化发生在库内的静态块中。
如果我没记错的话,该库的 iOS 版本被捆绑到一个框架中,该框架在应用程序启动时加载。该库的 Android 版本捆绑在一个模块中,该模块被延迟加载。(我知道这是一个问题,特别是因为我们链接到 OpenSSL,但这对于上下文可能很重要)。
我们使用 curl 构建了一个小型 HTTP 客户端,它允许用于从受信任的服务器下载一些数据 blob。
HTTP 客户端在其自己的线程上运行。它持有 a curl_multi_handle,并且任何传输开始时都将 a 附加curl_easy_handle到它,并返回一个Response包含缓冲区的句柄以从中读取接收到的字节,并在需要时用于控制传输。
由于 cURL 句柄不是线程安全的,因此对该句柄的任何操作(从现在开始称为任务)都被分派到 HTTP 客户端的线程,并且 boost::shared_future返回 a(我们可能想阻止或不阻止,具体取决于用例)。
以下是主循环结构的粗略概念:
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);
}
Run Code Online (Sandbox Code Playgroud)
附加到任务队列还执行 acurl_multi_wakeup(multi)以确保任务被执行(例如,添加新下载也是一个分派任务)。
到目前为止,我们只在 Android 上进行了测试,并且我们看到在某些情况下,被阻塞的 HTTP 客户端任务有时永远不会返回。
日志和堆栈跟踪显示我们等待 HTTP 客户端正在执行的任务,但客户端仍在轮询。一切似乎都表明它在附加任务时没有被唤醒。
我似乎无法在设备上本地复制该问题,但它经常发生,足以成为一个阻止程序问题。
我在这里有点不知所措,我真的不知道从哪里开始寻找重现问题的方法,更不用说修复它了。
我希望我提供了足够的上下文来开始进行有根据的猜测,甚至找到错误的根源!
谢谢阅读!
与传统的 *nix 操作系统相比,Android 和 iOS 等移动操作系统对后台进程的调度策略不同。移动操作系统往往会导致后台进程处于饥饿状态,以节省电池时间。这被称为background process optimization并将在应用程序进入后台时应用于应用程序的进程/线程。
从 Android 7 开始,后台进程不再通过CONNECTIVITY_ACTION广播获知网络事件,除非它们在清单中注册想要接收事件。
尽管在android 本机代码lobcurl中使用,但从本机库创建的线程将受到应用程序在清单中声明的权利(需要授予)的约束。
我知道阻塞问题是多么令人沮丧,因此我可以为您提供一个快速解决方法,供您尝试,直到问题得到解决。
curl_multi_poll()可以接收在代码中设置为 的超时very_large_number。此外,函数调用的最后一个参数是一个指向整数的指针numfds,该整数将填充池化时发生事件的文件描述符的数量curl_multi_pool()。
您可以利用这一点,通过以下方式构建解决方法:
very_large_number一个reasonably_small_numbernullptr为&numfdscurl_multi_poll用一个do ... 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 );
}
Run Code Online (Sandbox Code Playgroud)
选择一个合理的超时值(例如 1 秒、10 秒、60 秒……),这样您可以强力中断池化,同时又不会耗尽电池电量。
我添加了,check_for_other_conditions()以便您可以使用 is 来检查其他条件。以任务队列的大小为例,假设在某些情况下可能curl_multi_poll()会错过事件,尽管事件发生了,但这种额外的检查可以帮助打破循环并开始执行任务。
| 归档时间: |
|
| 查看次数: |
187 次 |
| 最近记录: |