[iOS] Deadlock: measureContent dispatch_syncs to main while holding the shadow tree lock
Maintainer thường phản hồi trong vòng 3 ngày
Chưa có ai nhận issue này.
Đánh giá
- Độ khó
- 4/5
- Thời gian dự kiến
- 3-5 ngày
- Mức phù hợp với người mới
- 48/100
- Loại issue
- Lỗi
- Độ rõ ràng
- Khá rõ ràng
- Mức độ hoạt động
- Sôi nổi
- Công nghệ
- objective-c, react-native
- Lĩnh vực
- mobile
Hướng nghiên cứu
Start with EnrichedTextInputViewShadowNode::measureContent and EnrichedTextViewShadowNode to trace the synchronous main-queue measurement described in the report; then inspect EnrichedTextInputView and its measureSize: path. Reproduce by swiping back from a native-stack screen containing an EnrichedTextInput while the header is visible. Done when measurement avoids the described lock cycle and the reported freeze no longer reproduces.
Do mô hình lập chỉ mục viết ra từ nội dung của issue.
Mô tả
Before submitting a new issue
- I tested using the latest version of the library, as the bug might be already fixed.
- I tested using a supported version of react native.
- I checked for possible duplicate issues, with possible answers.
Bug summary
On iOS, EnrichedTextInputViewShadowNode::measureContent can deadlock the app. When it runs off the main thread it does a dispatch_sync to the main queue to call measureSize: on the component view. But measureContent runs during a commit while that thread holds the shadow tree lock. If the main thread is meanwhile committing state of its own, it waits on the same lock, and neither side can proceed:
- Layout thread: holds the shadow tree commit lock →
measureContent→dispatch_sync(main)→ waits for main. - Main thread: react-native-screens'
RNSScreenStackHeaderConfigcommits header state from-viewDidLayoutSubviews→ waits for the shadow tree lock.
The app hangs until the watchdog kills it (0x8BADF00D).
In our app this reproduces reliably by swiping back (the interactive pop gesture) from any native-stack screen that contains an EnrichedTextInput. During the gesture both screens are mounted and the header config commits from viewDidLayoutSubviews almost every frame, so a measurement of the input soon collides with it.
EnrichedTextViewShadowNode uses the same dispatch_sync pattern, so EnrichedText is likely affected too, though we have only hit it with the input.
Proposed fix
We patch this locally and have shipped it to production. The mounted path measures without ever blocking on the main thread:
EnrichedTextInputViewkeeps an immutableNSAttributedStringsnapshot of its text storage, built with the same mock-character handlingmeasureSize:uses. It's guarded by anos_unfair_lockand refreshed on the main thread intryUpdatingHeight, just before the state update that triggers the re-measure.measureContentmeasures that snapshot on the layout thread (NSAttributedString's measuring APIs are thread safe, and the snapshot is immutable and unshared). If no snapshot exists yet, it returns a zero height instead of blocking. The view pushes a state update as soon as it has content, which forces a re-measure.
Unlike #339 (reverted in #417), this doesn't commit a fixed size through state, so the measurement follows width changes.
Library version
1.2.0 (also reproduced on 1.1.1)
Environment info
- React Native 0.88.0, New Architecture (Fabric)
- Expo SDK 58
- react-native-screens 4.30.0 (native stack)
- iOS 26 and 27, physical devices and simulator
Steps to reproduce
- Render an
EnrichedTextInputinside a screen of a native-stack navigator (react-native-screens) that shows a header. - Push that screen on top of another screen.
- Swipe back slowly with the interactive pop gesture, release, and repeat a few times.
- The app freezes; after several seconds iOS kills it with
0x8BADF00D. Pausing in the debugger shows the main thread waiting on the shadow tree mutex and the JS/layout thread insidedispatch_syncfromEnrichedTextInputViewShadowNode::measureContent.
Reproducible example repository
We don't have a standalone reproduction repo yet; We can put one together if the steps above aren't enough to reproduce it.
- Ngôn ngữ chính
- C
- Star
- 1.4k
- Fork
- 74
- Merge trung bình
- 3 ngày 4 giờ
- Pull request đã merge (30 ngày)
- 18
Chuẩn bị môi trường
- Không có Dockerfile hay tệp Docker Compose
- Có mẫu pull request
- Không có hướng dẫn đóng góp
Bắt đầu từ đâu
- Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
- Bình luận trên issue rằng bạn sẽ nhận — tránh hai người làm cùng một việc.
- Fork repository và làm thay đổi trên một nhánh.
- Mở pull request có tham chiếu số hiệu của issue.
Issue khác của software-mansion/react-native-enriched-html
-
[Feature request] Vertical spacing (margins) for headings and lists in htmlStyleCó thể đã có người làm @henrikra đã nhận 7 ngày trước. Đang mởenhancement
Độ khó 4/5 3-5 ngày Mức phù hợp với người mới 20/100
software-mansion/react-native-enriched-html#832 ·
Maintainer thường phản hồi trong vòng 3 ngày
-
bug
Độ khó 3/5 1-2 ngày Mức phù hợp với người mới 76/100
software-mansion/react-native-enriched-html#818 · 1 bình luận ·
Maintainer thường phản hồi trong vòng 3 ngày
-
[iOS] Tags not parsed on iOS below a certain string lengthCó thể đã có người làm @hejsztynx đã nhận 15 ngày trước. Đang mởbug
Độ khó 4/5 3-5 ngày Mức phù hợp với người mới 42/100
software-mansion/react-native-enriched-html#811 · 3 bình luận ·
Maintainer thường phản hồi trong vòng 3 ngày
-
bug
Độ khó 3/5 1-2 ngày Mức phù hợp với người mới 50/100
software-mansion/react-native-enriched-html#810 · 1 bình luận ·
Maintainer thường phản hồi trong vòng 3 ngày
-
Support for `<raw-text-block>`Đang mởenhancement
Độ khó 5/5 Hơn một tuần Mức phù hợp với người mới 35/100
software-mansion/react-native-enriched-html#803 ·
Maintainer thường phản hồi trong vòng 3 ngày
Tất cả issue của software-mansion/react-native-enriched-html
Issue tương tự
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 72/100
cyrusimap/cyrus-imapd#6640 ·
Maintainer thường phản hồi trong vòng 2 ngày
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 60/100
Maintainer thường phản hồi trong vòng 1 ngày
-
bug
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 68/100
GalusPeres/HomeTiles#139 · 1 bình luận ·
Maintainer thường phản hồi trong vòng 3 ngày
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 70/100
DaveGamble/cJSON#1122 ·
Maintainer thường phản hồi trong vòng 12 ngày
-
Type: Bug
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 76/100
apache/nuttx-apps#3942 ·
Maintainer thường phản hồi trong vòng 1 ngày