Windows पर वर्ष 2038 की समस्या को परखना
19 जनवरी 2038 को 03:14:07 UTC पर 1970 से सेकंड गिनने वाला 32-बिट का चिह्नित काउंटर ख़त्म हो जाता है। Windows की घड़ी उसके आगे भी चलती है - पर वे प्रोग्राम, फ़ाइल फ़ॉर्मैट और लाइब्रेरी नहीं चलतीं जिन्होंने अपनी 32-बिट प्रति रख छोड़ी है। यहाँ बताया गया है कि पूरी मशीन की तारीख़ 2038 पर किए बिना इन्हें एक ऐप में कैसे ढूँढें।
बग अब भी कहाँ छिपा हो सकता है
Windows की घड़ी 1601 से 100 नैनोसेकंड के क़दमों की 64-बिट गिनती है, इसलिए उसमें 2038 है ही नहीं। C रनटाइम लाइब्रेरी का time_t Visual Studio 2005 से डिफ़ॉल्ट रूप से 64-बिट है। जो बचता है वह वह कोड है जिसने 32-बिट समय चुना या रास्ते में उसका ऊपरी आधा हिस्सा खो दिया:
_USE_32BIT_TIME_Tके साथ कंपाइल किए गए 32-बिट बिल्ड, या जो सीधे_time32और__time32_tको कॉल करते हैं। Microsoft के अपने दस्तावेज़ चेताते हैं कि ऐसा ऐप 18 जनवरी 2038 के बाद विफल हो सकता है।- 64-बिट समय को
intयाlongमें रखना। Windows पर दोनों 32-बिट के हैं, 64-बिट प्रोग्राम में भी। - लाइब्रेरी, फ़ाइल फ़ॉर्मैट, नेटवर्क प्रोटोकॉल और डेटाबेस कॉलम जो 1970 से सेकंड 32 बिट में रखते हैं।
- वर्ष जोड़ने वाला कोड। बीस साल का लाइसेंस, तीस साल की ऋण-अनुसूची या 2040 तक मान्य सर्टिफ़िकेट इस सीमा को 2038 के आने से बहुत पहले पार कर लेते हैं।
एक ऐप में सीमा पार करना
यह सीमा UTC में परिभाषित है और --at सत्र के ज़ोन में पढ़ा जाता है, इसलिए पल ख़ुद लिखते समय ज़ोन को UTC पर तय कर दें। तैयार परिदृश्य में पहले से एक निरपेक्ष UTC पल है और उसे ज़ोन की ज़रूरत नहीं।
# परिदृश्य: सत्र ठीक सीमा पर शुरू होता है, 03:14:07 UTC chrono run "C:\apps\test.exe" --preset year-2038 --report session.txt # सीमा से सत्रह सेकंड पहले शुरू करें और ऐप को उसे लाइव पार करने दें chrono run "C:\apps\test.exe" --at 2038-01-19T03:13:50 --zone +00:00 --report session.txt # और पहले शुरू करें और 60 गुना रफ़्तार से चलाएँ - सीमा लगभग 14 सेकंड में आ जाती है chrono run "C:\apps\test.exe" --at 2038-01-19T03:00:00 --zone +00:00 --mode x60 # या आज की तारीख़ पर चलाएँ और ऐप खुला रहते हुए उसके पार कूद जाएँ chrono run "C:\apps\test.exe" --jump-after 5:2038-01-19T03:14:05 --zone +00:00
सीमा के एक सेकंड बाद चिह्नित 32-बिट काउंटर -2,147,483,648 हो जाता है, जो 13 दिसंबर 1901, 20:45:52 UTC पढ़ा जाता है। 1901 की कोई तारीख़, कोई ऋणात्मक संख्या, कोई आइटम जो अचानक एक्सपायर हो जाए या छँटाई में सबसे ऊपर आ जाए, तारीख़ के कोड से फेंका गया कोई अपवाद - ओवरफ़्लो बाहर से ऐसा ही दिखता है।
असली घड़ी को 2038 पर सेट करना यहाँ पहुँचने का दूसरा रास्ता है, और सबसे ज़्यादा तोड़ने वाला भी। सिस्टम की तारीख़ बदलने पर क्या होता है →
यह पक्का करना कि यह प्रोग्राम तक पहुँचा
जो परीक्षण इसलिए पास हो जाए कि प्रोग्राम ने 2038 कभी देखा ही नहीं, वह परीक्षण न होने से भी बुरा है। हर सत्र के अंत की रिपोर्ट बताती है कि प्रोग्राम ने कौन-सी घड़ी पढ़ी और कितनी बार:
Chrono Mock - session report
target: .\build\test.exe
verdict: WORKS - time substitution took effect (processes: 1)
every process that read time saw the session clock
session: fake clock reached 2038-01-19T03:14:08
real elapsed 1.3s, fake elapsed 1.3s
covered channels (substituted, with call counts, 10 calls in all):
- pid 21240: GetSystemTimeAsFileTime (5 calls)
- pid 21240: GetLocalTime (5 calls)
session वाली पंक्ति पुष्टि करती है कि ऐप की घड़ी सीमा के पार गई। कॉल की गिनती के साथ works निर्णय का मतलब है कि प्रोग्राम ने घड़ी पढ़ी और उसे 2038 की तारीख़ मिली; works partially उन चैनलों के नाम बताता है जो उसने किसी और रास्ते से पढ़े। निर्णयों का मतलब →
पास हुआ परीक्षण क्या साबित नहीं करता
- सिर्फ़ प्रोग्राम की अपनी घड़ी खिसकी। जो तारीख़ वह किसी फ़ाइल या डेटाबेस से लोड करता है, वह वही है जो वहाँ रखी है, इसलिए डेटा के भीतर 2038 की तारीख़ एक अलग परीक्षण है। तारीख़ कैलकुलेटर ऐसी तारीख़ें आपके लिए निकाल देता है:
chrono calc --base 2038-01-19T03:14:07 --zone +00:00 --shift +1s - जिस सर्वर से प्रोग्राम बात करता है, वह अब भी असली तारीख़ पर चलता है। उस तरफ़ की 32-बिट सीमा पहुँच से बाहर है, और जब सत्र प्रोग्राम को नेटवर्क कनेक्शन खोलते देखता है तो चेतावनी देता है।