HeadlinesBriefing HeadlinesBriefing.com

निर्धारित डिबगर निक्स बिल्ड में रेस कंडीशन खोजता है

Hacker News •
×

कुछ दिन पहले मैंने Rewind VM के बारे में लिखा था, एक निर्धारित वर्चुअल मशीन जहां निक्स बिल्ड का हर रन अपने इनपुट का एक शुद्ध फंक्शन है, थ्रेड शेड्यूलिंग शामिल! मैंने इसका इस्तेमाल निक्स बिल्ड में रेस कंडीशन को खोजने, पुनरूत्पादित करने और हल करने के लिए किया है, लेकिन यह मुझे थोड़ा पागल बना रहा है। यह कौन सी सुपरपावर है, और दूसरे इसका इस्तेमाल क्यों नहीं कर रहे हैं?

इंस्ट्रूमेंट ने जल्दी ही एक सोर्स पैनल, स्टैक फ्रेम्स, बुकमार्क, एक "कंपेयर" टैब, बहुत सारा जीडीबी सपोर्ट, थ्रेड लेन्स जो दिखाते हैं कि हर चरण में किसने सीपीयू पकड़ा था, और "चेक फ्रॉम हीर" जो रेस कंडीशन होने वाले बिल्ड को खोजने में मदद करता है। मैंने हर नए फीचर में यह सोचकर जाया कि यह एक बड़ा कोड-लिफ्ट होगा, लेकिन मैं हर बार एक ही चीज से ग्रसित हो गया: हर फीचर के कठिन हिस्से पहले से ही किए गए थे, और निक्स ने किए थे।

उदाहरण के लिए, एक डिबगर को कार्यक्रम के सटीक इनपुट, इसके डिबग सिंबल्स, इसके सोर्स, उसके नीचे की हर लाइब्रेरी के सोर्स, और एक तरीके की आवश्यकता होती है जिससे दूसरे अपने मशीन पर इस सब कुछ प्राप्त कर सकें। यह ठीक वैसे ही है जैसे एक डेरिवेशन, और निक्स इसे आसान बनाता है।

दो कैशियर, एक खाता

रेस कंडीशन का एक क्लासिक सरल उदाहरण दो थ्रेड्स द्वारा एक बैंक खाते में जमा करना है। हर जमा बैलेंस पढ़ता है, लेजर में एक पंक्ति लिखता है, फिर बैलेंस और जमा को स्टोर करता है। अगर एक कैशियर दूसरे के पढ़ने और स्टोर करने के बीच चलता है, तो वह दूसरे के जमों पर एक स्टेल बैलेंस लिख देता है।

static void deposit(int teller, long amount){long seen = balance;char line[64];int n = snprintf(line, sizeof line,"teller %d: %ld + %ld\n",teller, seen, amount);if (write(1, line, n) != n)return;balance = seen + amount;}

एक कैशियर जो दूसरे के पढ़ने और स्टोर करने के बीच चलता है, वह दूसरे के जमों पर एक स्टेल बैलेंस लिख देता है।

11

मेरे 16-कोर लैपटॉप पर, बैंक ने 1,000 रन में से 396 में पैसा खो दिया। taskset के माध्यम से एकल कोर पिन किए गए, इसमें 1,000 में से किसी में भी पैसा नहीं खोया: एकल कोर अक्सर जमा के बीच में थ्रेड्स नहीं बदलता, इसलिए रीविंड शेड्यूल को बाधित करता है।

रीविंड की वीएम में एक सीपीयू है, इसलिए उसका पहला रन बहुत अच्छे से हो जाता है। rewind check बिल्ड को बाधित शेड्यूल के तहत दोबारा चलाता है, हर बार गेस्ट कर्नल से अलग-अलग चरणों में रीशेड्यूलिंग की अनुरोध करता है, और पहले फेल को एक चरण तक कम कर देता है:

$ rewind check --where github:fzakaria/rewindvm#bank...step 3237 तय करता है: वहां रीशेड्यूलिंग रन को फेल कर देती है

passing: run 12feb5f832205a72, schedule 0

failing: run c2f1cfac0c288f3e, schedule 1 over steps 3237..3238

दो रन एक मशीन के हैं, निकाल के लिए समान, चरण 3237 तक, जहां केवल फेल होने वाला रीशेड्यूलिंग प्राप्त करता है।

मुफ्त चीज एक: इनपुट

चेक का तर्क एक डेरिवेशन है और यह एक फ्लेक रिफरेंस हो सकता है। निक्स की सुंदरता यह है कि यह डेरिवेशन के इनपुट को जानता है, इसलिए हमें बस यह सुनिश्चित करने की आवश्यकता है कि रन पुनरूत्पादनीय है। डेरिवेशन के इनपुट हैं: स्रोत, कंपाइलर, लाइब्रेरीज, कर्नल, और वीएम का कॉन्फिगरेशन। रीविंड निक्स डेरिवेशन के इनपुट को पूरा करता है, क्लोजर को एक रीड-ऑनली इरोफ्स इमेज में पैक करता है, और वीएम को उस पर बूट करता है। रन का आईडी इसके इनपुट का हैश है, ठीक वैसे ही जैसे स्टोर पथ, और रीविंड शो कमांड को दोबारा बनाने का कमांड प्रिंट करता है:

$ rewind show 12feb5f8

rewind nix /nix/store/cr8rl40rjb9cmmcd9sxn9mpdrhvp53jj-bank-0.1.0.drv --epoch --clock branches --name bank-0.1.0 # 12feb5f832205a72

जब बिल्ड सफल हो जाता है, तो गेस्ट हर आउटपुट का एनएआर हैश रिपोर्ट करता है, और रीविंड निक्स इसे होस्ट की कॉपी और हर बाइनरी कैश से निक्स के सब्स्टिट्यूट के साथ मिलाता है, केवल .narinfo फेच करता है:

$ rewind nix github:fzakaria/rewindvm#bank.../nix/store/27a4q7w90jzp4wg5kaaajvb64zll6yqg-bank-0.1.0 dbf0df3de84b7a84 matches your store

यह हमें मदद करता है कि वीएम के अंदर की गई बिल्ड मेरे लैपटॉप पर की गई बिल्ड के समान है, और वीएम का रन निक्स द्वारा पुनरूत्पादनीय है।

स्रोत: Hacker News · HeadlinesBriefing द्वारा सारांशित