مگرمچھ کے پیچھے سے ایک اور ہائیزن بگ

مگرمچھ کے پیچھے سے ایک اور ہائیزن بگ

$> set -o pipefail

$> fortune | head -1 > /dev/null && echo "Повезло!" || echo "Вы проиграли"
Повезло!

$> fortune | head -1 > /dev/null && echo "Повезло!" || echo "Вы проиграли"
Вы проиграли

یہاں fortune مشروط پروگرام کے بغیر exit(rand()).

کیا آپ وضاحت کر سکتے ہیں؟ یہاں کیا غلط ہے?

گیت-تاریخی ڈگریشن

میں ایک چوتھائی صدی قبل اس ہائیزن بگ سے پہلی بار واقف ہوا۔ پھر FaxNET میں گیٹ وے کے لیے اس کے ذریعے کئی یوٹیلیٹیز بنانا ضروری تھا۔ پائپ فری بی ایس ڈی کے تحت "چیکرز کھیلنا"۔ جیسا کہ توقع کی گئی تھی، میں نے خود کو ایک جدید اور کافی تجربہ کار پروگرامر سمجھا۔ اس لیے، میں نے غلطی سے نمٹنے پر خصوصی توجہ دیتے ہوئے، ہر ممکن حد تک احتیاط اور احتیاط سے کرنے کا ارادہ کیا۔

سینڈ میل اور uucp/uupc میں کیڑے سے نمٹنے کے میرے پچھلے تجربے نے "مکمل غلطی سے نمٹنے" میں میری مستعدی میں اضافہ کیا۔ اس کہانی کی تفصیلات میں غوطہ لگانے کا کوئی فائدہ نہیں ہے، لیکن میں نے اس ہائیزن بگ کے ساتھ دو ہفتوں تک 10-14 گھنٹے تک جدوجہد کی۔ اس لیے یاد آیا اور کل یہ پرانا شناسا دوبارہ ملنے کے لیے رک گیا۔

TL؛ DR جواب

افادیت۔ head کر سکتے ہیں سے چینل بند کریں fortune ابھی جیسے ہی وہ پہلی لائن پڑھتا ہے۔ اگر fortune ایک سے زیادہ لائنوں کو آؤٹ پٹ کرتا ہے، پھر متعلقہ کال write() ایک غلطی واپس کرے گا یا رپورٹ کرے گا کہ درخواست سے کم بائٹس آؤٹ پٹ ہیں۔ بدلے میں، محتاط غلطی سے نمٹنے کے ساتھ لکھا گیا fortune اس صورت حال کو اپنی خارجی حیثیت میں ظاہر کرنے کا حق رکھتا ہے۔ پھر تنصیب کی وجہ سے set -o pipefail کام کرے گا || echo "Вы проиграли".

تاہم، head وقت پر نہیں کر سکتے ہیں اس سے پہلے بند کرو fortune آؤٹ پٹ ڈیٹا کو ختم کر دے گا۔ پھر یہ کام کرے گا۔ && echo "Повезло!".

میرے آج میں سے ایک میں GNUMakefile ایسا ہے ٹکڑا:

echo '#define MDBX_BUILD_COMPILER "$(shell set -o pipefail; $(CC) --version | head -1 || echo 'Please use GCC or CLANG compatible compiler')"'

انسان میں ترجمہ کیا گیا۔

کے لیے یہاں عام ہے۔ GNU بنائیں۔ и مار آپشن کا استعمال کرتے ہوئے کمپائلر طریقے سے --version یہ پوچھتا ہے کہ وہ کون ہے، اور اگر آپشن تعاون یافتہ نہیں ہے، تو ایک سٹب ڈال دیا جاتا ہے۔ "براہ کرم GCC یا CLANG ہم آہنگ کمپائلر استعمال کریں".

پسند بوائلر پلیٹ کہیں بھی پایا جا سکتا ہے۔ یہ اس جگہ پر کافی عرصہ پہلے نمودار ہوا تھا اور ہر جگہ بالکل کام کرتا تھا (لینکس، سولاریس، او ایس ایکس، فری بی ایس ڈی، WSL وغیرہ)۔ لیکن کل میں altlinux پلیٹ فارم پر Elbrus 2000 (E2K) میں نے مشاہدہ کیا:

#define MDBX_BUILD_COMPILER "lcc:1.23.20:Sep--4-2019:e2k-v3-linux Please use GCC or CLANG compatible compiler"

سچ کہوں تو، میں نے اپنے پرانے "آشنا" کو فوری طور پر نہیں پہچانا۔ مزید برآں، پراجیکٹ کا پہلے ہی ایلبرس پر اور بہت سی مختلف تقسیموں کے تحت تجربہ کیا جا چکا ہے، بشمول Alt۔ مختلف کمپائلرز کے ساتھ، GNU Make اور bash کے ورژن۔ اس لیے، میں یہاں اپنی غلطی نہیں دیکھنا چاہتا تھا۔

جب مسئلہ کو دوبارہ پیش کرنے اور/یا یہ سمجھنے کی کوشش کی گئی کہ کیا ہو رہا ہے، تو مزید عجیب و غریب چیزیں ہونے لگیں۔
کمانڈ لائن ہجے:

echo "#define MDBX_BUILD_COMPILER '$(set -o pipefail; LC_ALL=C cc --version | head -1 || echo "Please use GCC or CLANG compatible compiler")'"

وقتاً فوقتاً یہ اضافی ٹیکسٹ تیار کرے گا، پھر نہیں... اکثر آپشنز میں سے ایک آپشن کافی دیر تک چپکا رہتا ہے، لیکن اگر آپ زیادہ دیر تک ٹہلتے ہیں، تو آپ کو ہمیشہ دونوں مل جاتے ہیں!

ظاہر کی، strace ہمارا سب کچھ! اور اسٹریس ٹائریڈ ٹائپ کرنے کے بعد، لیکن Enter دبانے کا وقت نہ ملا، میں نے اپنے پرانے دوست مسٹر ہیزن بگ اور ڈویلپرز کو پہچان لیا۔ مرتب کرنے والا میں 25 سال پہلے، پرانی یادیں… اور میں نے اداس ہو کر یہ نوٹ لکھنے کا فیصلہ کیا 😉

ویسے کسی بھی عزت نفس کی طرح ہائزن بگ، کے تحت strace دوبارہ پیدا نہ کرنے کو ترجیح دیتے ہیں۔

تو کیا ہو رہا ہے؟

  • افادیت۔ head اس کے پاس یہ حق ہے (یا اس کے بجائے، مجبور بھی ہے) کہ پڑھے جانے والے چینل کو جیسے ہی وہ مطلوبہ لائنوں کی تعداد پڑھتا ہے اسے بند کر دے۔
  • ڈیٹا تیار کرنے والا پروگرام مصنف (اس معاملے میں cc) کر سکتے ہیں متعدد لائنیں پرنٹ کریں اور مفت یہ متعدد کالوں کے ذریعے کریں۔ write().
  • اگر قاری کے پاس مصنف کی طرف سے ریکارڈنگ ختم ہونے سے پہلے اپنی طرف کا چینل بند کرنے کا وقت ہوگا، پھر مصنف کو ایک غلطی موصول ہوگی۔
  • رائٹر پروگرام حق ہے دونوں چینل لکھنے کی غلطی کو نظر انداز کرتے ہیں اور اسے اپنے تکمیلی کوڈ میں ظاہر کرتے ہیں۔
  • تنصیب کی وجہ سے set -o pipefail پائپ لائن کی تکمیل کا کوڈ غیر صفر (غلط) ہوگا اگر نتیجہ کم از کم ایک عنصر سے غیر صفر ہے، اور پھر یہ کام کرے گا۔ || echo "Please use GCC or CLANG compatible compiler".

اس بات پر منحصر ہے کہ رائٹر پروگرام سگنلز کے ساتھ کیسے کام کرتا ہے۔ مثال کے طور پر، پروگرام غیر معمولی طور پر ختم ہو سکتا ہے (غیر صفر/غلطی ختم ہونے کی حیثیت کی خودکار تخلیق کے ساتھ)، یا write() درخواست اور سیٹ سے کم بائٹس لکھنے کا نتیجہ واپس کر دے گا۔ errno = EPIPE.

الزام کون ہے؟

بیان کردہ کیس میں ہر چیز کا تھوڑا سا. میں ہینڈل کرنے میں خرابی۔ cc (lcc:1.23.20:Sep—4-2019:e2k-v3-linux) نہیں ہے۔ بے کار بہت سے معاملات میں احتیاط کی طرف سے غلطی کرنا بہتر ہے، حالانکہ یہ روایتی رویے کے لیے ڈیزائن کیے گئے بوائلر پلیٹ میں اچانک خامیوں کو ظاہر کرتا ہے۔

کیا؟

غلط:

fortune | head -1 && echo "Повезло, но вы рискуете!" || echo "WTF?"

درست طریقے سے:

  1. (fortune && echo "Успешно" || echo "Ошибка") | head -1

    یہاں، پائپ کی جلد بندش کو کمانڈ انٹرپریٹر کے ذریعے سنبھالا جائے گا جب نیسٹڈ پائپ لائن (قوسین کے "اندر") کی خدمت کرتے وقت۔ اس کے مطابق، اگر fortune اسٹیٹس میں بند چینل کو لکھنے میں غلطی کی اطلاع دے گا، پھر آؤٹ پٹ || echo "Ошибка" یہ کہیں نہیں ملے گا، کیونکہ چینل پہلے ہی بند ہے۔

  2. fortune | cat - | head -1 && echo "Успешно" || echo "Ошибка"

    یہاں افادیت ہے cat ایک damper کے طور پر کام کرتا ہے کیونکہ یہ غلطی کو نظر انداز کرتا ہے۔ EPIPE واپسی پر. ابھی نتیجہ نکالنے کے لیے یہی کافی ہے۔ fortune چھوٹی (کئی لائنیں) اور چینل بفر میں فٹ ہوجاتی ہیں (512 بائٹس سے ≈64K تک، زیادہ تر OS ≥4K میں)۔ ورنہ مسئلہ واپس آ سکتا ہے۔

صحیح طریقے سے عمل کرنے کا طریقہ EPIPE اور دیگر ریکارڈنگ کی غلطیاں؟

کوئی واحد صحیح حل نہیں ہے، لیکن سادہ سفارشات ہیں:

  • EPIPE ضرورت ہے عملدرآمد کرنا ضروری ہے (اور باہر نکلنے کی حالت میں ظاہر ہوتا ہے) جب ڈیٹا آؤٹ پٹ کرتے ہیں جس میں سالمیت کی ضرورت ہوتی ہے۔ مثال کے طور پر، آرکائیورز یا بیک اپ یوٹیلیٹیز کے آپریشن کے دوران۔
  • EPIPE نظر انداز کرنا بہتر ہے معلومات اور معاون پیغامات کی نمائش کرتے وقت۔ مثال کے طور پر، اختیارات پر معلومات ظاہر کرتے وقت --help یا --version.
  • اگر کوڈ تیار کیا جا رہا ہے تو اس سے پہلے پائپ لائن میں استعمال کیا جا سکتا ہے۔ | headپھر EPIPE نظر انداز کرنا بہتر ہے، بصورت دیگر باہر نکلنے کی حالت میں پروسیسنگ اور عکاسی کرنا بہتر ہے۔

میں اس موقع سے ٹیموں کا شکریہ ادا کرنا چاہوں گا۔ ایم سی ایس ٹی и altlinux عظیم پیداواری کام کے لیے۔ آپ کا عزم حیرت انگیز ہے!
کیپ اٹ اپ کیمریڈز، اوپر موسم خزاں میں ملاقاتیں!

شکریہ بیریز ٹائپنگ کی غلطیوں اور غلطیوں کو درست کرنے کے لیے۔
KDPV سے جارجی اے

ماخذ: www.habr.com

نیا تبصرہ شامل کریں