2010-02-10 12 views
5

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

  1. ए बी के लिए अनुरोध भेजता है। यह काम करता है। अब बी
  2. बी से उत्तर पढ़ने शुरू होता है। बी को उत्तर भेजता है। संबंधित लेखन() कॉल एक ईपीआईपीई त्रुटि देता है, और परिणामस्वरूप बी बंद() सॉकेट होता है। हालांकि, ए बंद() सॉकेट, और न ही यह दुर्घटनाग्रस्त हो गया।
  3. ए पढ़ा गया() कॉल रिटर्न 0, अंत-फ़ाइल का संकेत देता है। एक सोचता है कि बी ने समय से कनेक्शन बंद कर दिया।

उपयोगकर्ताओं को भी इस व्यवहार के रूपांतरों की सूचना दी है, जैसे:

  1. एक एक अनुरोध बी को यह आंशिक रूप से काम करता है भेजता है, लेकिन पूरे अनुरोध एक के लिखने भेजे जाने से पहले() कॉल EPIPE देता है, और नतीजतन एक करीबी() सॉकेट। हालांकि बी ने सॉकेट को बंद नहीं किया, और न ही यह दुर्घटनाग्रस्त हो गया।
  2. बी आंशिक अनुरोध पढ़ता है और फिर अचानक एक ईओएफ प्राप्त होता है।

समस्या यह है कि मैं स्थानीय रूप से इस व्यवहार को पुन: उत्पन्न नहीं कर सकता। मैंने ओएस एक्स और लिनक्स की कोशिश की है। उपयोगकर्ता विभिन्न प्रणालियों पर हैं, ज्यादातर ओएस एक्स और लिनक्स।

चीज़ें है कि मैं पहले से ही करने की कोशिश की और माना जाता है:

  • डबल पास() कीड़े (करीब() एक ही फाइल वर्णनकर्ता पर दो बार कहा जाता है): शायद नहीं के रूप में है कि EBADF त्रुटियों में परिणाम है, लेकिन होता मैंने उन्हें नहीं देखा है।
  • अधिकतम फ़ाइल डिस्क्रिप्टर सीमा को बढ़ा रहा है। एक उपयोगकर्ता ने बताया कि यह उसके लिए काम करता है, बाकी ने बताया कि यह नहीं था।

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

उत्तर

3

शायद आप strace की कोशिश कर सकते (या इसके GUI cousin।): http://modperlbook.org/html/6-9-1-Detecting-Aborted-Connections.html

मुझे लगता है कि आपकी समस्या को यहाँ वर्णित एक से संबंधित है: http://blog.netherlabs.nl/articles/2009/01/18/the-ultimate-so_linger-page-or-why-is-my-tcp-not-reliable

दुर्भाग्यवश मेरे पास similar problem स्वयं है लेकिन इसे दी गई सलाह के साथ तय करने में सक्षम नहीं हो सका। हालांकि, शायद यह SO_LINGER चीज आपके लिए काम करती है।

+0

यह पता चला कि सर्वर की फ़ाइल डिस्क्रिप्टर को EPOLLET ध्वज के साथ एपोल कतार में जोड़ा गया था जो गलत लगता है। – user206268

+2

बिल्कुल वही जवाब नहीं जिसे मैं ढूंढ रहा था लेकिन आपके द्वारा लिंक किया गया टीसीपी पृष्ठ बहुत ही जानकारीपूर्ण है! यह अभी भी Archive.org द्वारा नीचे है: http://ia700609.us.archive.org/22/items/TheUltimateSo_lingerPageOrWhyIsMyTcpNotReliable/the-ultimate-so_linger-page-or-why-is-my-tcp-not-reliable .html – Hongli

2
  • shutdown() सॉकेट अंतिम बिंदुओं में से एक पर बुलाया गया है हो सकता है।

  • तो दोनों ओर कांटा और एक बच्चे प्रक्रिया निष्पादित कर सकते हैं, यह सुनिश्चित करें कि FD_CLOEXEC (करीब-ऑन-कार्यकारी) झंडा अगर आप का इरादा नहीं किया यह विरासत में मिला जा करने के लिए के लिए सॉकेट फ़ाइल वर्णनकर्ता पर सेट किया गया है बच्चे द्वारा। अन्यथा बच्चे की प्रक्रिया (सॉकेट या अन्यथा) आपके सॉकेट कनेक्शन में हेरफेर कर सकती है।

+0

धन्यवाद, लेकिन मेरे कार्यक्रम में न तो स्थितियां लागू हैं। – Hongli

0

मैं यह भी जांचूंगा कि मध्य में कोई स्नीकी फ़ायरवॉल नहीं है। यह संभव है कि मार्ग पर एक मध्यवर्ती अग्रेषण नोड RST भेजता है।कि नीचे ट्रैक करने के लिए सबसे अच्छा तरीका में वर्णित के रूप पाठ्यक्रम the packet sniffer की है

+0

... यूनिक्स डोमेन सॉकेट पर? यह एकमात्र स्थानीय प्रोटोकॉल है। – ephemient

+0

ओह ... शूट, मैं पूरी तरह से याद किया। धन्यवाद। –

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