【问题标题】:FORTIFY_SOURCE: FD_SET: file descriptor >= FD_SETSIZE. Calling abort()FORTIFY_SOURCE:FD_SET:文件描述符 >= FD_SETSIZE。调用中止()
【发布时间】:2015-08-11 20:42:00
【问题描述】:

我是一名安卓程序员。

今天我运行了一个 android 应用程序,当时我遇到了这种类型的错误。

FORTIFY_SOURCE:FD_SET:文件描述符 >= FD_SETSIZE。调用 abort()。

所以如果有人知道这个问题的答案,请回复我。

【问题讨论】:

  • 那么我们如何在没有代码的情况下检查错误?
  • 顺便说一句,如果您遇到此问题,可以使用 Google Play Services ProviderInstaller API 来解决。有关如何使用它的更多信息,请参阅本文:developer.android.com/training/articles/…

标签: android


【解决方案1】:

您的进程打开的文件描述符或套接字过多,当达到操作系统限制时,您的应用程序将被终止。

您的应用程序不太可能合法地用完所有资源,这很可能是泄漏。您很可能错过了对套接字或文件资源的 Close() 调用。

我在使用相同代码的各种 Android 设备上遇到了这个问题。最常见的错误签名是:

01-27 15:50:52.431 I/DEBUG   (  172): pid: 12444, tid: 19014, oom: 0, name: DrmRequestHandl  >>> YOUR_PACKAGE_NAME <<<
01-27 15:50:52.431 I/DEBUG   (  172): signal 6 (SIGABRT), code -6 (SI_TKILL), fault addr --------
01-27 15:50:52.517 I/DEBUG   (  172): Abort message: 'FORTIFY_SOURCE: FD_SET: file descriptor >= FD_SETSIZE. Calling abort().'

您可以检查设备调用的描述符限制:

adb shell ulimit -n

作为解决问题的第一步,您可能需要弄清楚泄漏的资源类型。您可以通过以下方式找出应用的进程 ID:

 adb shell ps

然后使用进程 ID,当您的应用仍在运行时,您可以检查打开的描述符(您需要 root 访问权限或可调试的应用程序/ROM):

adb shell ls -l  /proc/[YOUR_PROCESS_ID]/fd

对于进程 12345,它将类似于:

adb shell ls -l  /proc/12345/fd

这将列出描述符。在较旧的 android 版本上,列表中可以有 1024 个项目,在 Lollipop 上,我看到 2048 作为默认限制。

对于可调试应用,您可以使用run-as(参见@Joe 的评论):

adb shell run-as com.mycompany.myapplication ls -l /proc/12345/fd

【讨论】:

  • 您不需要 root 访问权限来查看文件描述符:adb shell run-as $yourApplicationId ls -l /proc/$yourProcessId/fd/。例如,adb shell run-as com.mycompany.myapplication ls -l /proc/12345/fd
  • 我编写了一个简单的 shell 脚本(在 macOS 上测试)来监控 Android 应用的打开文件描述符的数量:gist.github.com/jhansche/322965fa3c3a6179114bc3ac8e4337ec
  • @Joe 你是我们的救星,伙计,上帝保佑你!!
【解决方案2】:

当我在“Intel x86 Atom_64”模拟器中测试我的 Vulkan 渲染器时,出现了名为“anon_inode:sync_file”的大量 fd 泄漏。

不确定是否与此有关,但症状完全相同: https://gitlab.freedesktop.org/mesa/mesa/-/issues/1949

无论如何,它从未在 Google API/Play 模拟器或真实设备中发生过。

顺便说一句,API 级别是 29。

【讨论】:

    【解决方案3】:

    我不得不一次下载数百个文件并遇到错误。

    您可以使用以下命令检查打开的描述符(感谢@Habib!)

    adb shell ps
    

    在列表中找到您的应用程序 PID 并使用另一个命令(再次感谢 :)

    adb shell run-as YOUR_PACKAGE_NAME ls -l  /proc/YOUR_PID/fd
    

    我在通常的启动中看到大约 150 个打开的描述符。下载文件时有 700 多个。他们的数量只会在几分钟后减少,看起来 Android 在后台释放了他们,而不是当你可以在流中 close 时。

    唯一可行的解​​决方案是使用自定义线程池来限制并发。这是 Kotlin 代码:

    private val downloadDispatcher = Executors.newFixedThreadPool(8).asCoroutineDispatcher()
    
    private suspend fun downloadFile(sourceUrl: String, destPath: String, progressBlock: suspend (Long) -> Unit) = withContext(downloadDispatcher) {
        val url = URL(sourceUrl)
        url.openConnection().apply { connect() }
        url.openStream().use { input ->
            FileOutputStream(File(destPath)).use { output ->
                val buffer = ByteArray(DEFAULT_BUFFER_SIZE)
                var bytesRead = input.read(buffer)
                var bytesCopied = 0L
                while (bytesRead >= 0) {
                    if (!coroutineContext.isActive) break
                    output.write(buffer, 0, bytesRead)
                    bytesCopied += bytesRead
                    progressBlock(bytesCopied)
                    bytesRead = input.read(buffer)
                }
            }
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-04-17
      • 2023-03-22
      • 2017-02-12
      • 1970-01-01
      • 2014-05-08
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多