5 điểm bởi GN⁺ 2025-01-24 | 4 bình luận | Chia sẻ qua WhatsApp
  • 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ự: setenvgetenv

    • 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_FILESSL_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

 
carnoxen 2025-01-24

setenv không an toàn luồng, và C không muốn sửa điều đó

Hàm setenv lại gây rắc rối nữa rồi.

 
y15un 2025-01-24

Tôi sẽ đặt tiêu đề là "Tính không an toàn luồng của stdlib trong C thì ngay cả Rust vốn được xem là an toàn cũng không cứu nổi". :)

 
halfenif 2025-01-24

Tôi đã hiểu rõ ràng.

 
GN⁺ 2025-01-24
Ý 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

    • Trong thư viện chuẩn Rust, set_varremove_var sẽ yêu cầu khối unsafe {} ở edition 2024
    • Tài liệu hiện tại có nhắc đến vấn đề an toàn, nhưng việc ban đầu thiết kế các hàm này là an toàn vốn là một sai lầm
  • Một bản vá cho glibc đã làm getenv an 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àn

    • Những người bảo trì thư viện chuẩn C tỏ ra miễn cưỡng trong việc làm setenv an 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ồng
    • Người bảo trì của Musl không tin chắc rằng vấn đề này là không thể giải quyết
  • Việ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

    • Linus và kernel khá thực dụng trong việc xử lý các lỗi POSIX, nhưng glibc vẫn đang tụt lại phía sau
    • Việc cung cấp getenv_r(), đồng bộ nó với setenv(), 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

    • Dùng tệp cấu hình như YAML thay cho biến môi trường được xem là cách tốt hơ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ự

    • Có vẻ như chúng ta đã đánh mất khả năng build và debug mã cục bộ mà không cần cloud và container
  • Đâ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

    • Những bản tường trình xử lý sự cố chi tiết như vậy mang lại trải nghiệm gần nhất với việc tự mình điều tra
  • env::set_var giờ đây là không an toàn

    • Có thể gọi an toàn trong chương trình đơn luồng
    • Trên Windows, nó luôn an toàn trong cả chương trình đơn luồng lẫn đa luồng
    • Trên các hệ điều hành khác, với chương trình đa luồng, lựa chọn an toàn duy nhất là không dùng set_var hoặc remove_var
  • Điều này gợi nhớ đến trải nghiệm setproctitle không hoạt động trong một số codebase nhất định

    • Sau khi import numpy, setproctitle không còn hoạt động nữa, vì trong quá trình khởi tạo numpy, lời gọi getenv hoặc setenv đã khiến địa chỉ của environ bị thay đổi