Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[iOS] ReactNativeBlobUtilNetwork @synchronized NSMapTable crash trigger com.apple.root.default-qos EXC_BAD_ACCESS KERN_INVALID_ADDRESS #313

Open
YadongChen opened this issue Nov 9, 2023 · 1 comment

Comments

@YadongChen
Copy link

YadongChen commented Nov 9, 2023

Env

  • react-native: 0.72.4
  • Route: react-native-navigation: 7.37.0
  • Crash Report: react-native-firebase: 17.5.0
  • react-native-blob-util: Both 0.17.3 and 0.19.2 have tried

react-native-blob-util Usage

In our business scenarios, sometimes we will access and download multiple icon image URLs and cache them when the App starts.

在我们的业务场景中,有些时候,我们会在App启动时,访问下载多个icon image url,并缓存

The code for a single download request is as follows:

单个下载请求代码如下:

const promise = ReactNativeBlobUtil.config({
    path, // save to the path
}).fetch('GET', url, {});

promise
    .then((response) => {
        // Delete the temp file if the download failed.
        if (response.respInfo.status !== 200) {
            ReactNativeBlobUtil.fs.unlink(path);
        } else {
            // ...
        }
    })
    .catch((error) => {
        // ...
    });
};

return promise;

Firebase Crash Report

Similar reports are generated in the Firebase Crash Report of our two versions of the App(Use 0.17.3 and 0.19.2 of react-native-blob-util respectively). As shown below:

在我们的两个版本的App (分别使用 react-native-blob-util0.17.30.19.2 )的Firebase Crash Report中,均产生了类似的Report。如下图:

Snipaste_2023-11-09_13-43-21

Moreover, this type of Crash-Report is distributed quite evenly, and is generally found on iOS 16+ versions, as well as various iPhone models.

并且,这类Crash-Report的分布相当均匀,普遍在iOS 16+版本上,以及各类iPhone机型

【Note: The same business code and related dependencies have no similar Crash Report in Android】

【注意:同样的业务代码和相关依赖项,在Android中无类似Crash Report】

Analysis

After investigating our business code, as well as the error stack in the above Firebase Crash Report, I have several inferences.

在调查了我们的业务代码,以及上述Firebase Crash Report中的错误堆栈后,我有了几个推论。

However, due to my unfamiliarity with the implementation of this library, I did not find the root cause, so it can only be regarded as a guess.

但是受限于对于这个库实现的不熟悉,我没有找到根本的原因,因此只能算是猜想。

If readers have any ideas or inspirations, they are very welcome. I would be very honored to receive any suggestions.

如果各位阅读者有任何的想法或者启发,都将是非常欢迎的,对于任何的建议我都感到非常的荣幸。

Generation of Task-Id

I noticed that in js fetch function, Use your own calculation method of UUID.

我注意到在js fetch function 中,使用了自己的UUID计算方式。

Although it seems to be reliable, it will at least return a string like "0." for calculation. But I'm not sure if there is a pitifully small chance of duplicate values appearing here.

虽然似乎它是可靠的,最低限度也会返回 "0." 这样的字符串进行计算。但是我不确定是否会有几率小得可怜的重复值会出现在这里。

As a result, when subsequent operations on NSMapTable are performed, problems related to using Task Id as key are triggered?

从而导致后续操作NSMapTable时,触发以Task Idkey的相关问题?

Strange grow / reclaim / load of NSMapTable

In the screenshot of the report above, after calling method setObject of object requestsTable, the data structure NSMapTable performs several operations:

上方的报告截图中,在调用requestsTable对象的setObject方法后,NSMapTable这个数据结构进行了几个操作:

  1. first grow
  2. Then reclaim does some recycling

    (Is it possible here that value marked as NSMapTableWeakMemory is recycled ? )

    (这里是否存在可能,回收了标记为NSMapTableWeakMemoryvalue ?)
  3. Then the part about Automatic Reference Counting (ARC), the related operations of reading and returning WeakMemory?

    然后是自动引用计数(ARC)的部分,读取和返回WeakMemory的相关操作?

Is there any possible conflict between reclaim and subsequent read?

这里是否存在reclaim和后续read的一些冲突可能?

Possible concurrency issues

I noticed that ReactNativeBlobUtilNetwork.mm has nicely declared some code to prevent concurrency:

我注意到ReactNativeBlobUtilNetwork.mm有很好的声明一些防止并发的代码:

@synchronized([ReactNativeBlobUtilNetwork class]) {
    // ...
}

However, when I use it in react-native, as the business requirements above say, we may have multiple icon image urls that need to be requested.

但是,当我在react-native中使用时,如上方业务要求所说,我们可能有多个icon image url需要请求。

For example:

  • forEach - await ReactNativeBlobUtil fetch,

  • Or Promise.all - multi ReactNativeBlobUtil fetch

What if the number of requests looping through my outer layer exceeds the threshold? For example:

如果当我的外层的请求循环数量,超过阈值?例如:

// ...
self.taskQueue.maxConcurrentOperationCount = 10;
// ...
defaultConfigObject.HTTPMaximumConnectionsPerHost = 10;
// ...
defaultConfigObject.timeoutIntervalForRequest = timeout/1000;
// ...

Is there possible incorrect concurrent use that may affect synchronized and ReactNativeBlobUtilNetwork?

是否可能存在错误的并发使用,影响synchronized ReactNativeBlobUtilNetwork的可能?

If so, is there a more recommended approach here?

如果是这样,这里是否有更推荐的做法?

Possibly incorrect cache clearing operation

Due to historical legacy code (no longer possible to know the reason), we tried to follow cache-file-management in the judgment of ReactNativeBlobUtil - response.【Refer to the Code example above】

由于历史遗留代码(原因不可考),我们在ReactNativeBlobUtil的response判断中,试图遵循文档中所述的缓存清理 【参考上方Code示例】

But the two writing methods are weirdly merged, using res.flush() instead of ReactNativeBlobUtil.fs.unlink.

但是怪异的合并了两种写法,将ReactNativeBlobUtil.fs.unlink替代了res.flush()

Is this not recommended? Or is there a possibility of violating react-native-blob-util’s design?

这是否是不推荐的?或者存在违反react-native-blob-util设计的可能?


If readers have any ideas or inspirations, they are very welcome. I would be very honored to receive any suggestions.

如果各位阅读者有任何的想法或者启发,都将是非常欢迎的,对于任何的建议我都感到非常的荣幸。

@miteshdb
Copy link

+1. I noticed the same crash on Firebase Crash Report today.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants