-
Sự cố chỉ xảy ra trên ARM64
- Trong quá trình chuyển mã I/O mạng của EdgeDB từ Python sang Rust, đã phát sinh vấn đề các bài kiểm thử thỉnh thoảng thất bại trên runner CI ARM64.
- Ban đầu trông giống như deadlock, nhưng thực tế là tiến trình đã bị crash và test runner không phát hiện ra điều đó.
-
Giả thuyết ban đầu
- Để hiểu vì sao vấn đề chỉ xảy ra trên ARM64, nhóm đã xem xét sự khác biệt của mô hình bộ nhớ.
- Mô hình bộ nhớ của Intel nghiêm ngặt hơn, trong khi ARM có mô hình bộ nhớ yếu hơn.
-
Gỡ lỗi trên máy CI
- Nhóm đã kết nối trực tiếp vào runner ARM64 trên AWS để điều tra vấn đề.
- Tiến trình bị crash và để lại core dump; việc phân tích nó đã giúp xác định nguyên nhân của vấn đề.
-
Nguyên nhân thực sự: setenv và getenv
setenv không an toàn trong môi trường đa luồng và có thể gây crash khi tương tác với getenv.
- Việc gán lại biến môi trường được xác định là nguyên nhân của vấn đề.
-
Liên hệ với openssl_probe
- Sự cố xảy ra khi
openssl-probe thiết lập các biến môi trường SSL_CERT_FILE và SSL_CERT_DIR.
- Quá trình
rust-native-tls của Rust thiết lập các biến môi trường này đã gây ra crash.
-
Vì sao chỉ xảy ra trên ARM64 Linux
- Chỉ khi nhiều điều kiện cùng khớp thì crash mới xảy ra; số lượng biến môi trường và lỗi I/O là một phần trong các điều kiện đó.
-
Giải pháp
- Nhóm quyết định chuyển từ backend
rust-native-tls/openssl của reqwest sang rustls.
- Dự án Rust có kế hoạch đánh dấu các hàm thiết lập môi trường là unsafe, còn dự án glibc sẽ cải thiện tính an toàn theo luồng của
getenv.
4 bình luận
setenvkhông an toàn luồng, và C không muốn sửa điều đóHàm
setenvlại gây rắc rối nữa rồi.Tôi sẽ đặt tiêu đề là "Tính không an toàn luồng của
stdlibtrong C thì ngay cả Rust vốn được xem là an toàn cũng không cứu nổi". :)Tôi đã hiểu rõ ràng.
Ý kiến Hacker News
Trong edition tiếp theo của Rust, các hàm thiết lập biến môi trường sẽ bị chuyển thành không an toàn. Điều này có thể ảnh hưởng đến các crate gây xung đột
set_varvàremove_varsẽ yêu cầu khốiunsafe {}ở edition 2024Một bản vá cho glibc đã làm
getenvan toàn hơn, nhưng C vẫn cho phép truy cập trực tiếp vào môi trường nên vẫn chưa thể an toàn hoàn toànsetenvan toàn cho đa luồng, nhưng ít nhất nên định nghĩa một API mới an toàn cho luồngViệc gặp lỗi liên quan đến môi trường trên Linux gần như được xem là một nghi thức trưởng thành
getenv_r(), đồng bộ nó vớisetenv(), và đưa ra cảnh báo ở thời điểm biên dịch/liên kết có lẽ đã giúp giải quyết vấn đềViệc dùng biến môi trường cho cấu hình là một phần của phong trào "12-factor app", nhưng điều này bị cho là một cách làm ngớ ngẩn
Các máy CI chạy trên Amazon AWS có ưu điểm là cung cấp người dùng root thực sự
Đây là một bài viết rất hay về việc đào sâu vào những lỗi không trực quan
env::set_vargiờ đây là không an toànset_varhoặcremove_varĐiều này gợi nhớ đến trải nghiệm
setproctitlekhông hoạt động trong một số codebase nhất địnhnumpy,setproctitlekhông còn hoạt động nữa, vì trong quá trình khởi tạonumpy, lời gọigetenvhoặcsetenvđã khiến địa chỉ củaenvironbị thay đổi