2013-05-24 37 views
10

Nếu tôi nhận được một "Tên hoặc dịch vụ chưa biết" ban đầu (EAI_NONAME), lệnh gọi getaddrinfo() tiếp theo sẽ chuyển thẳng đến dns thay vì kiểm tra bộ nhớ cache đầu tiên (nhật ký nscd hiển thị không có lần tra cứu nào, tcpdump hiển thị lưu lượng truy cập đến máy chủ DNS). Nếu cuộc gọi đầu tiên thành công trong việc nhận địa chỉ, từ đó trở đi, tất cả các cuộc gọi getaddrinfo() sẽ chuyển tới nscd trước, như mong đợi.bằng cách sử dụng getaddrinfo() chỉ kiểm tra bộ nhớ cache nscd lần đầu tiên nếu DNS lần

Tôi đang biên dịch chống lại glibc-2.13 cho Linux cánh tay. Trong rc.d của tôi, nscd được bắt đầu trước daemon của tôi. nscd được đặt để không cho phép cache được chia sẻ và duy trì bộ nhớ cache lưu trữ. Tôi đang sử dụng nscd từ busybox (0,47). nsswitch.conf được thiết lập để máy chủ kiểm tra cache/files/dns. hosts.conf được thiết lập để kiểm tra các tập tin/ràng buộc.

Trình nền của tôi đang gọi getaddrinfo().

Tôi có nhật ký gỡ lỗi để chạy nscd và chúng cho thấy rằng máy khách bắt đầu đọc phản hồi DNS đóng với lỗi "Lỗi ống".

Sau đó, nó sẽ hiển thị các nỗ lực GAI từ các trình tiện ích khác đang cố gắng sử dụng bộ nhớ cache (vì vậy tôi biết nó không bị khóa hoặc bất kỳ điều gì), nhưng daemon đã nhận EAI_NONAME không bao giờ liên lạc lại với nscd để thực hiện tra cứu bộ nhớ cache.

Nếu tôi khởi động lại daemon, tôi nhận được cùng một hành vi, nếu lần truy vấn DNS đầu tiên hết lần nữa.

Có điều gì đó trong glibc làm mất hiệu lực liên kết daemon của tôi với bộ nhớ cache không? Có cách nào để kết nối lại daemon của tôi vào bộ nhớ đệm mà không cần khởi động lại nó (tương tự như việc buộc tải lại resolv.conf qua res_init()) không?

+1

"* ... có cách nào để kết nối lại daemon của tôi vào bộ nhớ cache mà không cần khởi động lại nó ... *" bạn có cố gắng làm cho daemon của bạn gọi 'getaddrinfo()' "** thực sự **" thường xuyên không. Hãy nói 100 ++ lần? Hãy thử và theo dõi quyền truy cập vào 'nscd'. Tôi không thể kiểm tra điều này ở đây, nhưng có thể có một cơ hội daemon của bạn quyết định kiểm tra kết nối 'nscd' sau đó một lần nữa và nếu thành công sử dụng nó từ đó trở đi. – alk

+0

"* Nếu tôi khởi động lại daemon, tôi nhận được cùng một hành vi ... *" bạn đang đề cập đến daemon của riêng bạn ở đây, không phải để 'nscd', phải không? – alk

+0

Btw: Tôi có ý tưởng được đề cập ở trên để kiểm tra các nguồn của eglibc. – alk

Trả lời

4

alk mentions in his comment, thử lại getaddrinfo() hơn 100 lần nên buộc truy vấn nscd.


Để hiểu tại sao, chúng ta hãy tham gia một peek nhanh vào dòng chảy của thi bêngetaddrinfo().

  1. getaddrinfo() calls gaih_inet.

  2. gaih_inet() thực hiện các hoạt động sau đây trên __nss_not_use_nscd_hosts:

    • Kiểm tra cho dù đó là một số nguyên dương?
    • Tăng số tiền đó.
    • Kiểm tra xem nó có vượt quá số lần thử lại NSS_NSCD_RETRY không?

      - Nó cố gắng truy vấn nscd CHỈ nếu cả hai điều kiện trên đều được thỏa mãn.

    Ngoài ra khi cố gắng một truy vấn để nscd, đếm được ngay lập tức thiết lập lại bằng không do đó bỏ qua nscd cho NSS_NSCD_RETRY lần tiếp theo getaddrinfo() được gọi.

  3. Cũng __nss_not_use_nscd_hosts được sửa đổi trong nội bộ bởi nscd ở các vị trí sau

Dựa trên việc trên, có thể kết luận rằng getaddrinfo() KHÔNG truy vấn nscd mỗi lần duy nhất. Ngoài ra, trạng thái nội bộ của nscd (được xác định bởi __nss_not_use_nscd_hosts) quyết định xem getaddrinfo() có kết thúc bằng cách gọi nscd hay không.

Để thực sự buộc cách của một người quanh giới hạn 100 retry, người ta có thể sửa đổi NSS_NSCD_RETRY và xây dựng lại libc để đi chệch khỏi hành vi tiêu chuẩn. Nhưng tôi không thực sự chắc chắn nếu điều này sẽ không dẫn đến bất kỳ hồi quy không mong muốn khác.

Tham chiếu: Patch đã giới thiệu logic __nss_not_use_nscd_hosts trong getaddrinfo().

Các vấn đề liên quan