2013-08-19 36 views
6

Một vài tháng trước, tôi viết một ứng dụng CGI cho Linux sử dụng popen() để đọc đầu ra của lệnh, và sau đó tôi đóng ống với fclose().sử dụng fclose để ống popen là một lỗi nghiêm trọng?

Bây giờ, tôi đọc cho các đường ống gần là cần sử dụng pclose().

Sổ tay nói:

Giá trị trả về từ popen() là một bình thường tiêu chuẩn I/O hoạt động trong tất cả các khía cạnh tiết kiệm mà nó phải được đóng lại với pclose() hơn fclose(3).

Mã của tôi là như thế này:

if ((NULL != (f = popen(command.value, "r")))) { 
    //do something 
    fclose(f); 
} 

Câu hỏi của tôi là:

Sai lầm của tôi có một mối quan tâm an ninh? Chương trình hiện đang được sản xuất. Trong các thử nghiệm nó không làm bất cứ vấn đề gì. Thực sự cần thiết, hãy vá nó bằng cách sử dụng pclose() thay vì fclose()? Lưu ý: Tôi chỉ mở PIPE một lần trong chương trình.

Hôm nay, ở nhà địa phương của tôi, tôi làm một số thử nghiệm và fclose()pclose() không trả lại EOF cho biết lỗi.

+2

Bạn có hành vi Không xác định : Đọc ['pclose()' vs 'fclose()'?] (Http://cboard.cprogramming.com/cplusplus-programming/97147-pclose-vs-fclose.html): Hàm '_pclose' tìm kiếm ID tiến trình của bộ xử lý lệnh (CMD.EXE) bắt đầu bằng lệnh '_popen' liên quan, thực hiện lệnh gọi' _cwait' trên bộ xử lý lệnh mới và đóng luồng trên đường ống liên kết.' –

+0

Có một số bài viết SO liên quan đến câu hỏi của bạn: 1. ['fclose ()/pclose() 'có thể chặn trên một số con trỏ tập tin] (http://stackoverflow.com/questions/1736983/fclose-pclose-may-block-on-some-file-pointers) và [Cách xử lý ống gần trong unix ? '(fclose() của pclose())'?] (http://stackoverflow.com/questions/5548364/how-close-pipe-handle-in-unix-fclose-of-pclose) –

+0

cảm ơn, tôi sẽ sửa chữa bởi vì thực sự quan trọng. Bây giờ, tôi nhìn vào tác động. – carlos

Trả lời

5

Nếu bạn sử dụng fclose trên đường ống, bạn sẽ bị rò rỉ mô tả tập tin, vì fclose sẽ không giải phóng con trỏ tệp trong hạt nhân (được tạo khi bạn tạo đường ống từ tệp của nó).

Trong khi thử nghiệm của bạn cho đến nay vẫn chưa hiển thị bất kỳ sự cố nào, hãy chạy chương trình của bạn 3000 lần (hoặc bao nhiêu tệp mô tả được phép, trở lên của int tôi nghĩ) và xem khi nào bạn không còn có thể tạo ống nữa .

+2

Thông thường 'fclose' trên luồng stdio thực sự * không * đóng bộ mô tả đường ống bên dưới (nó được lưu trữ trong' fp -> _ fileno' hoặc bất kỳ trường nào được đặt tên), do đó, nó bị rò rỉ nhiều hơn so với rò rỉ fd. – torek

10

Theo this thread, sử dụng fclose thay vì pclose có nghĩa là quá trình ở đầu kia của đường ống không bị gặt hái, do đó nó vẫn được giữ lại.

+0

rất cảm ơn, sau đó tôi không đóng ống, nó là xấu, cảm ơn. – carlos

0

Tôi vừa phát hiện ra (sau 10 năm) rằng tôi đã nhầm khi sử dụng fclose cho một số cuộc gọi popen, đang chạy trên máy chủ Windows 2008. Nó hoạt động (tức là không sụp đổ), và tôi không quan tâm đến mã trả về trên các cuộc gọi đó.

Nhưng tôi cần mã trả về của luồng popen cuối cùng và đóng được thực hiện đúng cách với pclose.

Có hiệu ứng lạ khi trả về mã lỗi 0 (có thể thu thập mã trả về trước đây không phải là quy trình pclosed), ngay cả khi lệnh không thành công, tạo lỗi rất lạ trong mã, điều này có thể dẫn đến lỗi nghiêm trọng bởi vì người gọi nghĩ rằng lệnh đã hoạt động.

Vì vậy, nó không chỉ là một vấn đề mô tả rò rỉ, nó có thể giới thiệu các lỗi chức năng trong mã của bạn, (ngay cả khi ứng dụng chạy trong vài giây và bạn không quan tâm đến mô tả rò rỉ)

+0

BTW, nó là hệ điều hành rất cụ thể. OP đã hỏi một cách rõ ràng về Linux. Và các bản phân phối Linux thông thường có phần mềm libc miễn phí, vì vậy OP nên nghiên cứu mã nguồn của việc thực thi libc cụ thể của mình. –

+0

ok, nhưng những gì đã xảy ra với tôi trên cửa sổ cũng có thể xảy ra trên các hệ thống khác. –

+0

Ngoại trừ khía cạnh phần mềm tự do đang thay đổi rất nhiều cách giải quyết vấn đề đó. Nếu libc (và kernel) của bạn là phần mềm miễn phí, bạn có thể kiểm tra và nghiên cứu mã nguồn của nó (và hiểu điều gì xảy ra). –