2013-09-27 10 views
6

लिनक्स के "आदमी बंद" ने चेतावनी दी है (SVR4, 4.3BSD, POSIX.1-2001):नज़दीकी() की वापसी मूल्य की जांच नहीं कर रहा है: वास्तव में कितना गंभीर है?

Not checking the return value of close() is a common but nevertheless serious programming error. It is quite possible that errors on a previous write(2) operation are first reported at the final close(). Not checking the return value when closing the file may lead to silent loss of data. This can especially be observed with NFS and with disk quota.

मेरा मानना ​​है कि कर सकते हैं कि इस त्रुटि आम (कम से कम आवेदन पत्र में है, मेरे पास कोई कर्नेल हैकर हूँ)। लेकिन कैसे गंभीर यह है, आज या पिछले तीन दशकों में किसी भी समय? विशेष रूप से:

क्या डेटा के इस तरह के मौन हानि का एक सरल, पुनरुत्पादित उदाहरण है? यहां तक ​​कि एक विकृत व्यक्ति भी करीब() के दौरान सिगकिल भेजना पसंद करता है?

अगर इस तरह के एक उदाहरण मौजूद है, डेटा हानि सिर्फ

printf("Sorry, dude, you lost some data.\n"); से ज्यादा शान से संभाला जा सकता है?

+0

भले ही मैं आमतौर पर परिणाम की जांच करता हूं, कई सालों बाद, ऐसा लगता है कि ऐसा लगता है। इस उत्तर की प्रतीक्षा करें। – chux

+0

उद्धरण इंडेंट करने के लिए धन्यवाद, एल्क। मुझे> कमांड के बारे में पता नहीं था। –

+1

मैं आम तौर पर 'बंद' के परिणाम या विफलता की परवाह नहीं करता हूं। मुझे लगता है कि अगर आप एक बहुत मजबूत सर्वर सॉफ्टवेयर विकसित करना चाहते हैं तो आप परवाह करेंगे। लेकिन बग की कई अन्य संभावनाएं हैं :-) बीटीडब्लू, कुछ मुफ्त सॉफ्टवेयर 'क्लोज़' विफलता के बारे में परवाह करते हैं। –

उत्तर

6

[H]ow serious is it, today or at any point in the past three decades?

विशिष्ट अनुप्रयोगों प्रक्रिया डेटा। वे कुछ इनपुट उपभोग करते हैं, और परिणाम उत्पन्न करते हैं। तो, दो सामान्य मामले हैं जहां close() एक त्रुटि लौटा सकता है: इनपुट (केवल-पढ़ने के लिए) फ़ाइल बंद करते समय, और फ़ाइल को बंद करते समय जो अभी उत्पन्न या संशोधित किया गया था।

ज्ञात परिस्थितियां जहां close() एक त्रुटि लौटाती है स्थायी डेटा को डेटा लिखने/फ़्लश करने के लिए विशिष्ट होती है। विशेष रूप से, स्थायी ऑपरेटिंग (close(), fsync(), या fdatasync() पर) लिखने से पहले ऑपरेटिंग सिस्टम स्थानीय रूप से डेटा को कैश करने के लिए आम है; यह रिमोट फाइल सिस्टम के साथ बहुत आम है, और यही कारण है कि एनएफएस का उल्लेख मैन पेज पर किया गया है।

मुझे केवल पढ़ने-योग्य इनपुट फ़ाइल को बंद करते समय कभी भी कोई त्रुटि नहीं आई है। सभी मामलों में मैं सोच सकता हूं कि किसी भी सामान्य फाइल सिस्टम का उपयोग करके वास्तविक जीवन में यह कहां हो सकता है, जहां एक विनाशकारी विफलता है, कर्नेल डेटा संरचना भ्रष्टाचार जैसे कुछ। यदि ऐसा होता है, तो मुझे लगता है कि close() त्रुटि केवल एकमात्र संकेत नहीं हो सकता है कि कुछ गलत है।

रिमोट फाइल सिस्टम पर एक फ़ाइल को लिखते समय, close()-टाइम त्रुटियां बेहद आम हैं, यदि स्थानीय नेटवर्क ग्लिच के लिए प्रवण होता है या बस बहुत सारे पैकेट छोड़ देता है। एक अंतिम उपयोगकर्ता के रूप में, मैं चाहता हूं कि मेरे एप्लिकेशन मुझे बताए कि फ़ाइल में लिखते समय कोई त्रुटि हुई है या नहीं। आमतौर पर रिमोट फाइल सिस्टम से कनेक्शन पूरी तरह टूट जाता है, और तथ्य यह है कि एक नई फाइल को लिखना असफल रहा, उपयोगकर्ता के लिए पहला संकेतक है।

यदि आप close() वापसी मूल्य की जांच नहीं करते हैं, तो एप्लिकेशन उपयोगकर्ता से झूठ बोलता है। यह इंगित करेगा (यदि कोई अन्य त्रुटि नहीं है तो त्रुटि संदेश की कमी से), कि फ़ाइल सही ढंग से लिखी गई थी, जब वास्तव में यह नहीं था, और एप्लिकेशन को बताया गया था; आवेदन सिर्फ संकेत को नजरअंदाज कर दिया। यदि उपयोगकर्ता मेरे जैसा है, तो वे एप्लिकेशन से बहुत नाखुश होंगे।

सवाल यह है कि, उपयोगकर्ता डेटा आपके लिए कितना महत्वपूर्ण है? अधिकांश वर्तमान अनुप्रयोग प्रोग्रामर बिल्कुल परवाह नहीं करते हैं। बेसिल स्टैरेनकेविच (मूल प्रश्न पर टिप्पणी में) बिल्कुल सही है; close() त्रुटियों की जांच करना कुछ प्रोग्रामर कुछ परेशान नहीं करते हैं।

मुझे विश्वास है कि रवैया ग़लत है; उपयोगकर्ता डेटा के लिए cavalier उपेक्षा।

यह स्वाभाविक है, हालांकि, उपयोगकर्ताओं के पास कोई स्पष्ट संकेत नहीं है कि किस एप्लिकेशन ने अपने डेटा को दूषित कर दिया है।मेरे अनुभव में अंतिम उपयोगकर्ता सामान्य रूप से ओएस, हार्डवेयर, ओपन सोर्स या फ्री सॉफ़्टवेयर को दोष देते हैं, या स्थानीय आईटी समर्थन; इसलिए, प्रोग्रामर के लिए देखभाल करने के लिए कोई दबाव, सामाजिक या अन्यथा कोई दबाव नहीं है। क्योंकि केवल प्रोग्रामर इस तरह के विवरणों से अवगत हैं, और अधिकांश प्रोग्रामर परवाह नहीं है, स्थिति को बदलने के लिए कोई दबाव नहीं है।

(मुझे पता है कि उपर्युक्त प्रोग्रामर मेरे गले से नफरत करेंगे, लेकिन कम से कम मैं ईमानदार हूं। इस तरह की चीजों को इंगित करने के लिए मुझे सामान्य प्रतिक्रिया मिलती है कि यह एक दुर्लभ घटना है, यह जांचने के लिए संसाधनों का अपशिष्ट होगा। यह संभव है .. लेकिन मैं एक के लिए अधिक CPU चक्र खर्च करने और प्रोग्रामर को कुछ प्रतिशत अधिक भुगतान करने के लिए तैयार हूं, अगर इसका मतलब है कि मेरी मशीन वास्तव में अधिक अनुमानित रूप से काम करती है, और मुझसे कहता है अगर यह साजिश खो दिया है, के बजाय चुपचाप अपने डेटा भ्रष्ट)

Is there a simple, reproducible example of such silent loss of data?

मैं तीन तरीकों में से जानते हैं:।

  1. यूएसबी स्टिक का उपयोग करें, और अंतिम write() के बाद इसे बाहर निकालें लेकिन close() से पहले। दुर्भाग्यवश, अधिकांश यूएसबी स्टिक में हार्डवेयर होता है जो इसे जीवित रहने के लिए डिज़ाइन नहीं किया गया है, इसलिए आप यूएसबी स्टिक को ब्रिक कर सकते हैं। फाइल सिस्टम के आधार पर, आपका कर्नेल भी घबरा सकता है, क्योंकि अधिकांश फाइल सिस्टम इस धारणा के साथ लिखे गए हैं कि यह कभी नहीं होगा।

  2. एनएफएस सर्वर सेट अप करें, और एनएफएस सर्वर और क्लाइंट के बीच सभी पैकेट ड्रॉप करने के लिए iptables का उपयोग कर इंटरमीटेंट पैकेट बूंदों का अनुकरण करें। सटीक परिदृश्य सर्वर और क्लाइंट, माउंट विकल्प, और संस्करणों पर निर्भर करता है। हालांकि, परीक्षण परीक्षण दो या तीन आभासी मशीनों का उपयोग करके स्थापित करने के लिए अपेक्षाकृत आसान होना चाहिए।

  3. close() समय पर एक त्रुटि त्रुटि अनुकरण करने के लिए एक कस्टम फाइल सिस्टम का उपयोग करें। वर्तमान कर्नेल आपको टीएमएफएफ या लूपबैक माउंट्स को मजबूर नहीं करते हैं, केवल एनएफएस माउंट्स, अन्यथा यह अंतिम लिखने के बाद फाइल सिस्टम को बल-अनमाउंट करके अनुकरण करना आसान होगा लेकिन close() से पहले। (वर्तमान फाइलें केवल उस फाइल सिस्टम पर खुली फाइलें हैं, तो इन्हें उमाउंट से इनकार कर दें।) एप्लिकेशन परीक्षण के लिए, close() पर त्रुटि लौटाते हुए tffs का एक संस्करण बनाते हैं, यदि फ़ाइल मोड इंगित करता है कि यह वांछनीय है (उदाहरण के लिए, अन्य लिखने योग्य लेकिन नहीं अन्य पठनीय या अन्य निष्पादन योग्य, यानी -??????-w-) काफी आसान और सुरक्षित होगा। यह वास्तव में डेटा को दूषित नहीं करेगा, लेकिन यह जांचना आसान होगा कि अगर कर्नेल रिपोर्ट (समय का) डेटा भ्रष्टाचार बंद कर देता है तो आवेदन कैसे व्यवहार करता है।

+0

यूएसबी स्टिक परिदृश्य निश्चित रूप से सरल और प्रतिदिन की गणना करता है। और डेटा हानि की रिपोर्टिंग, जबकि खोए गए डेटा को बहाल करने के रूप में खुश नहीं है, * चुप डेटा हानि से बेहतर * है। –

+0

किसी मित्र की टिप्पणियों का पैराफ्रेश: POSIX एक I/O त्रुटि लौटने से() को बंद करने के लिए उपयोग किया जाता है; यह अभी भी की आवश्यकता नहीं है। लिनक्स कर्नेल स्रोत से: ext2, ext3, ext4, NTFS और FAT कोई त्रुटि नहीं लौटा सकता है; एनएफएस कर सकते हैं; अन्य फाइल सिस्टम शायद नहीं कर सकते हैं। (एनएफएस ने कभी भी पीओएसईक्स का सम्मान नहीं किया।) तो बंद करने की जांच() * समय से पहले हटाए गए थंबड्राइव का पता लगा सकता है। –

+2

@ कैमिली गौडिस्यून: लिनक्स में, लिनक्स में क्लोज़() त्रुटियां तब होती हैं जब कर्नेल फाइल-सिस्टम 'विशिष्ट' स्ट्रक्चर फाइल_ऑपरेशंस 'में' -> फ्लश 'हैंडलर त्रुटि देता है। 3.11 पर, केवल exofs, fuse, nfs, और cifs निर्दिष्ट करते हैं (ecryptfs भी करता है, लेकिन यह केवल अंतर्निहित फाइल सिस्टम हैंडलर को कॉल करता है), इसलिए * वर्तमान में * वे केवल वे हैं जो 'क्लोज़() 'के दौरान त्रुटि लौटा सकते हैं। इसका मतलब यह नहीं है कि वे कभी नहीं करेंगे; प्रगति होती है। अन्य सभी फाइल सिस्टम पर, यह सुनिश्चित करने के लिए कि डेटा वास्तव में स्टोरेज को सफलतापूर्वक हिट करता है, और यह इन पर भी चोट नहीं पहुंचाता है, एक 'fsync() '/' fdatasync() 'आवश्यक है (* अभी के लिए *)। –

6

POSIX's close() कॉलिंग errno को जन्म दे सकती करने के लिए स्थापित किया जा रहा:

  1. EBADF: खराब फ़ाइल संख्या
  2. EINTR: बाधित सिस्टम कॉल
  3. EIO: I/O त्रुटि (पर POSIX विशिष्टता अंक 6 से)

विभिन्न त्रुटियां विभिन्न मुद्दों को इंगित करती हैं:

  1. EBADF एक प्रोग्रामिंग त्रुटि इंगित करता है, क्योंकि प्रोग्राम को ट्रैक किया जाना चाहिए कि कौन सी फाइल/सॉकेट डिस्क्रिप्टर अभी भी खुले हैं। मैं इस त्रुटि के लिए गुणवत्ता प्रबंधन कार्रवाई का परीक्षण करने पर विचार करता हूं।

  2. EINTR के रूप में यह स्पष्ट नहीं है समारोह लौटे या नहीं के बाद कि क्या फ़ाइल/सॉकेट वर्णनकर्ता पारित कर दिया मान्य है (: http://lkml.org/lkml/2002/7/17/165 लिनक्स के तहत यह propably नहीं है) सबसे कठिन को संभालने के लिए हो रहा है। इस त्रुटि को देखते हुए आपको सिग्नल को संभालने के कार्यक्रम के तरीके की जांच करनी चाहिए।

  3. EIO केवल मैन-पेजों में उल्लिखित विशेष कंडिटन के तहत दिखाई देने की उम्मीद है। हालांकि कम से कम सिर्फ इस त्रुटि को ट्रैक करना चाहिए, में ऐसा लगता है कि वास्तव में कुछ गलत हो गया था।

इन सभी त्रुटियों में से प्रत्येक में पकड़े जाने का कम से कम एक अच्छा कारण है, तो बस इसे करें! ;-)

संभव विशिष्ट प्रतिक्रियाओं:

  1. स्थिरता पर ध्यान न देने EBADF स्वीकार्य हो सकता है के संदर्भ में, लेकिन त्रुटि ऐसा नहीं करेगा। जैसा कि कहा गया है कि आपका कोड ठीक करें क्योंकि प्रोग्राम वास्तव में यह नहीं जानता कि यह क्या कर रहा है।

  2. EINTR का निरीक्षण करने से सिग्नल जंगली चल रहा है। यह अच्छा नहीं है। निश्चित रूप से मूल कारण के लिए जाओ। चूंकि यह अस्पष्ट है कि क्या वर्णनकर्ता बंद हो गए हैं या सिस्टम के लिए नहीं जाते हैं, एएसएपी को पुनरारंभ करें।

  3. EIO में चल रहा है निश्चित रूप से हार्डवेयर * 1 में गंभीर विफलता को निष्क्रिय कर सकता है। हालांकि, सिस्टम की दृढ़ता से अनुशंसित शटडाउन से पहले यह केवल ऑपरेशन को पुनः प्रयास करने के लायक हो सकता है, हालांकि EINTR के लिए समान चिंताएं लागू होती हैं, यह अनिश्चित है कि वर्णनकर्ता वास्तव में बंद हो गया है या नहीं। अगर इसे बंद कर दिया गया तो इसे फिर से बंद करना एक बुरा विचार है, क्योंकि यह पहले से ही किसी अन्य थ्रेड द्वारा उपयोग में लाया जा सकता है। शटडाउन और हार्डवेयर * 1 प्रतिस्थापन Asap के लिए जाएं।


* 1 हार्डवेयर यह एक ब्रोडर भावना यहाँ में देखा जाना चाहिए: एक डिस्क के रूप में एक एनएफएस सर्वर में कार्य करता है, इसलिए EIO बस गलत कॉन्फ़िगर सर्वर या नेटवर्क या जो कुछ भी होने के कारण में शामिल है सकता है एनएफएस कनेक्शन।

+0

हमम ... 'बंद' विफल होने पर आपको क्या करना चाहिए? निरस्त करें? पुनः प्रयास करें? रद्द करना? नज़रअंदाज़ करना? – usr2564301

+1

@ जोंगवेयर: किसी भी मामले में इसे गंभीर घटना के रूप में लॉग करें, मूल कारण ढूंढें और इसे ठीक करें! चाहे "निरस्त करें, पुनः प्रयास करें, अनदेखा करें" आवेदन की आलोचना पर निर्भर करता है, उदा। चाहे वह एक विमान या खेल हो। चाहे आप एनएसए या स्क्रिप्ट बच्चे हों। – alk

+0

@ जोंगवेयर: कृपया मेरा अद्यतन उत्तर देखें। – alk

संबंधित मुद्दे