HeadlinesBriefing HeadlinesBriefing.com

Go রানটাইম বাগ: 32-বিট এম্বেডেড লিনাক্স ক্র্যাশ

Hacker News •
×

আমাদের দৈনন্দিন কাজ সাধারণত লিনাক্স এবং নিরাপত্তা বিষয়গুলোর চার ओर ঘूमে, সফটওয়্যার স্ট্যাকের গভীরে। তবে, আপনি যা ভাবতে পারেন তার চেয়ে বেশি ঘন ঘন, আমরা এমন অ্যাপ্লিকেশনগুলো ডিবাগ করতে শেষ হয়ে যাই যা অনেক বেশি উচ্চতরে চলছে। কখনও কখনও এমন সমস্যার মূল লিনাক্স কার্নেলে থাকে, কখনও কখনও অন্য জায়গায়। এই ব্লগ পোস্টে আমরা দেখিয়েছি কিভাবে আমরা Go রানটাইমের ভিতরে একটি বাগ খুঁজে পেয়েছি এবং তা ঠিক করেছি। হালকা সময়ে একটি গ্রাহক জানিয়েছে যে Go ভাষায় লিখিত একটি অ্যাপ্লিকেশন তাদের এম্বেডেড লিনাক্স সিস্টেমে সময়Samayে ক্র্যাশ হয়। ক্র্যাশहमेशা একই মরণনাশক ত্রুটির সাথে হয়, যার স্বাক্ষর হল: runtime: netpoll: eventfd ready for 5।প্রথমে আমরা ধরে নিয়েছি যে অ্যাপ্লিকেশন নিজেই বাগযুক্ত। কিন্তু ত্রুটিটি আরও নিকটে পর্যালোচনা করার পরে, এটি Go এর নেটপোল মেকানিজমের একটি অভ্যন্তরীণ ধারণা না থাকার মতো দেখল। ত্রুটিটি সorce/runtime/netpoll_epoll.go-এ netpoll()- থেকে আসে: যদি ev. Events != linux. EPOLLIN হয়, তবে throw("runtime: netpoll: eventfd ready for something unexpected")। এই কোড পথে, নেটপোল কোড EPOLLIN-কে একমাত্র ফায়ারিং ইভেন্টের रूपে আশা করে, কিন্তু এটি 5 পায়, যা EPOLLIN|EPOLLOUT। কেন epoll plötzlich EPOLLIN- এর বেশি ইভেন্ট রিপোর্ট করল, যখন কোড শুধু EPOLLIN- এর জন্য অনুরোধ করেছিল? গভীরে যেতে আগে, আমরা ত্রুটি বার্তাটি একটি সার্চ ইঞ্জিনে ফেলে দিলাম, আশা করলে যে কেউ আগে এই সমস্যার মুখোমুখি হয়েছে। এইভাবে আমরা সরাসরি Go প্রকল্পের ইস্যু ট্র্যাকারে একটি রিপোর্টে পৌঁছালাম: runtime: netpoll: eventfd ready for something unexpected। এই ইস্যুটি genau আমরা যে মরণনাশক ত্রুটি দেখেছি তার ব্যাখ্যা করে। এছাড়াও, এটি একটি 32-বিট ARM এম্বেডেড লিনাক্স সিস্টেমেও ঘটে! রিপোর্টাররা এছাড়াও নোট করেছেন যে ক্র্যাশ দীর্ঘ সময় চলমান অ্যাপ্লিকেশনে ঘটে। এটি আমাদের গ্রাহকের বর্ণনার সাথেও মেলে। বিঙ্গো! এই ইস্যুটি মার্চ ২০২৫ থেকে খোলা এবং অসমাধিত অবস্থায় পড়েছে। Go এর মেইনটেইনাররা এছাড়াও এই সমস্যা ঠিক করার একটি প্রচেষ্টা প্রত্যাখ্যান করেছেন। এই ইস্যুর মন্তব্য থেকে আমরা শিখেছি যে এই মরণনাশক ত্রুটি শুধুমাত্র 32-বিট ARM এবং i386 লিনাক্স সিস্টেমে দেখায়, সব ধরনের কার্নেল সংস্করণের সাথে। কিছু কার্নেল খুব পুরনো, কিছু নতুন। কোনো রিপোর্টার x86_64 বা arm64 সিস্টেমে এটি দেখেনি।প্রাথমিকে আমরা সন্দেহ করেছি যে epoll 32-বিট ARM বা i386-এ ভিন্নভাবে আচরণ করে। কিন্তু আমরা এই ধারণাটি দ্রুত ত্যাগ করেছি কারণ epoll কার্নেলের জেনেরিক কোর কোড। কেন এটি শুধু 32-বিট ARM বা i386-এ স্পুরিয়াস ইভেন্ট সেট ফেরত দেবে? এখনও, ত্রুটি শুধু 32-বিট সিস্টেমে দেখানোর Tatsache আমাদেরকে ব্যাথিত রাখে। পরবর্তী ধাপ olarak, আমরা Go এর নেটপোল কোডে epoll ব্যবহারের পর্যালোচনা করেছি। একটি LLM-এর সাহায্যে, আমরা src/runtime/netpoll_epoll.go-এ গিয়েছি, 32-বিটের ঝুঁকিপূর্ণ বিষয়গুলো যেমন পূর্ণান্তর রূপান্তরে ফোকাস করে। পর্যালোচনাটি প্রকাশ করেছে যে Go এর নেটপোল কোড struct epoll_event- এর data ফিল্ড ব্যবহার করে। লিনাক্স epoll কার্নেলে একটি 8 বাইটের কুকি সংরক্ষণ করতে পারে এবং এটি ফায়ারিং ইভেন্টের অংশ হিসেবে ব্যবহারকারী স্থান으로 ফেরত দেয়। অ্যাপ্লিকেশন এই কুকি ব্যবহার করে একটি ইভেন্টে মেটাডেটা সংযুক্ত করে, উদাহরণস্বরূপ বিভিন্ন ইভেন্ট সোর্সকে আলাদা করতে। struct epoll_event { __poll_t events; /* ev.

Events in Go netpoll */ __u64 data; /* ev. Data in Go netpoll */ }; Go রানটাইমের গভীরে, মূল ইভেন্ট হ্যান্ডলারকে জানতে হচ্ছে যে কোনো ইভেন্ট ইভেন্ট fd-এ pertenecে কিনা অথবা সকেট fd-এ। এটি ev. Data-কে তার ভিতরের ইভেন্ট fd অবজেক্টের ঠিকানার সাথে তুলনা করে নির্ধারণ করে: if *(**uintptr)(unsafe.

Pointer(&ev. Data)) == &netpoll Event Fd {...}। কোডে আরও অগ্রসর হলে, আমরা দেখেছি যে ev. Data নেটপোল ইভেন্ট fd-এ একটি কাঁচা পয়েন্টার ধরে রাখে অথবা প্রতিটি সকেটের জন্য একটি poll Desc অবজেক্টের একটি ট্যাগ করা পয়েন্টার ধরে রাখে। পয়েন্টার ট্যাগ একটি কাউন্টার, fdseq, যা পুনর্ব্যবহৃত poll Desc অবজেক্ট들을 আলাদা করে। এ পর্যন্ত সব ঠিক আছে। একই ফিল্ডে কাঁচা পয়েন্টার এবং ট্যাগ করা পয়েন্টার মিশ্রণ আমাদের কাছে संदिग्ध লাগল। কিন্তু এটি কীভাবে ক্র্যাশ থেকে সম্পর্কিত holding, এখনও স্পষ্ট নয়। Go কীভাবে মেমোরিতে ট্যাগ করা পয়েন্টার들을 বসায়, এর পর্যালোচনা করলে অবশেষে মূল কারণ প্রকাশ পায়। 32-বিট সিস্টেমে, একটি পয়েন্টার 4 বাইট اشغال করে যখন data ফিল্ড 8 বাইট আশা করে। এই আকারের অমিল পয়েন্টার মান সংরক্ষণ করার সময় ট্রంకেট করে। উপরের 4 বাইট রূপান্তরের সময় শূন্য করা হয়। যখন রানটাইম পরে ট্রাঙ্কেট করা পয়েন্টারের তুলনা মূল ইভেন্ট fd ঠিকানার সাথে করে, তখন...

উৎস: Hacker News · সারাংশ: HeadlinesBriefing