နောက်ထပ် Heisenbug သည် မိကျောင်းကို ကျော်သွားသည်

နောက်ထပ် Heisenbug သည် မိကျောင်းကို ကျော်သွားသည်

$> set -o pipefail

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

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

ဒါဟာဖြစ်ပါတယ် fortune conditional program မပါပဲ exit(rand()).

ရှင်းပြနိုင်မလား။ ဒီမှာ ဘာဖြစ်နေတာလဲ?

သီချင်းစာသား- သမိုင်းဆိုင်ရာ ကွဲလွဲမှု

လွန်ခဲ့တဲ့ ရာစုနှစ်ရဲ့ လေးပုံတစ်ပုံလောက်က ဒီ Heisenbug နဲ့ ပထမဆုံး သိကျွမ်းခဲ့တယ်။ ထို့နောက် FaxNET ရှိ gateway အတွက် utilities အများအပြားကို ဖန်တီးရန် လိုအပ်ပါသည်။ ပိုက် FreeBSD အောက်တွင် "ကစားကွက်များ"။ မျှော်လင့်ထားသည့်အတိုင်း၊ ကျွန်ုပ်သည် မိမိကိုယ်ကို အဆင့်မြင့်ပြီး အတွေ့အကြုံရှိ ပရိုဂရမ်မာတစ်ဦးဟု ယူဆပါသည်။ ထို့ကြောင့် အမှားအယွင်းများကို အထူးဂရုပြု၍ တတ်နိုင်သမျှ ဂရုတစိုက်နှင့် ဂရုတစိုက်လုပ်ဆောင်ရန် ရည်ရွယ်ပါသည်။

ပေးပို့စာမေးလ်နှင့် uucp/uupc တွင် ချို့ယွင်းချက်များနှင့် ကိုင်တွယ်ဖြေရှင်းခြင်းဆိုင်ရာ ကျွန်ုပ်၏ယခင်အတွေ့အကြုံသည် “သေချာသောအမှားအယွင်းကို ကိုင်တွယ်ခြင်း” တွင် ကျွန်ုပ်၏လုံ့လဝီရိယကို ပေါင်းထည့်ပါသည်။ ထိုဇာတ်လမ်း၏အသေးစိတ်အချက်အလက်များကို စေ့စေ့ငုကြည့်ရန်မှာ အဓိပ္ပါယ်မရှိသော်လည်း၊ ဤ Heisenbug ကို နှစ်ပတ်ကြာအောင် 10-14 နာရီကြာ ရုန်းကန်ခဲ့ရသည်။ ထို့ကြောင့် သတိရမိသည်နှင့် မနေ့ က ဤအသိအကျွမ်းဟောင်းသည် နောက်တစ်ကြိမ် လည်ပတ်ရန် ရပ်တန့်သွားခဲ့သည်။

TL;DR အဖြေ

အသုံးဝင်သည် head နိုင် ချန်နယ်ကို ပိတ်ပါ။ fortune တစ်ကြိမ် ပထမစာကြောင်းကို ဖတ်ပြီးတာနဲ့ ရှိရင် fortune လိုင်းတစ်ခုထက်ပို၍ ထွက်ပြီးနောက် သက်ဆိုင်ရာခေါ်ဆိုမှု write() တောင်းဆိုသည်ထက် ဘိုက်များ အထွက်နည်းကြောင်း အမှားတစ်ခု ပြန်ပေးမည် သို့မဟုတ် အစီရင်ခံပါမည်။ တစ်ဖန် ဂရုတစိုက် အမှားအယွင်း ဖြင့် ရေးထား သည်။ fortune ဤအခြေအနေကို ၎င်း၏ ထွက်ပေါက်အခြေအနေတွင် ထင်ဟပ်ဖော်ပြပိုင်ခွင့်ရှိသည်။ ထို့နောက် တပ်ဆင်မှုကြောင့် ဖြစ်သည်။ set -o pipefail အလုပ်လုပ်ပါလိမ့်မယ်။ || echo "Вы проиграли".

သို့သျောလညျး head အချိန်မီ မဆောင်ရွက်နိုင်ပါ။ အရင်ပိတ် fortune data output ပြီးသွားပါလိမ့်မယ်။ ပြီးရင် အလုပ်ဖြစ်လိမ့်မယ်။ && echo "Повезло!".

ငါ့ရဲ့ ဒီနေ့ တယောက်ထဲ GNUMakefile အဲဒီလိုရှိတယ်။ အပိုင်း:

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

လူသားအဖြစ် ဘာသာပြန်ပါသည်။

ဒီနေရာမှာ အဖြစ်များပါတယ်။ GNU လုပ်ပါ и ကား Bash compiler တွင် option ကိုအသုံးပြုသည်။ --version သူက ဘယ်သူလဲလို့ မေးတယ်၊ ရွေးစရာကို ပံ့ပိုးမပေးဘူးဆိုရင် ဆောင်းပါးတိုကို ထည့်ပေးတယ်။ "ကျေးဇူးပြု၍ GCC သို့မဟုတ် CLANG တွဲသုံးနိုင်သော compiler ကိုသုံးပါ".

ကြိုက်တယ်။ ဘွိုင်လာပြား ဘယ်နေရာမှာမဆို တွေ့နိုင်ပါတယ်။ ၎င်းသည် ကြာမြင့်စွာကတည်းက ဤနေရာ၌ ပေါ်လာပြီး နေရာတိုင်းတွင် ကောင်းမွန်စွာအလုပ်လုပ်ခဲ့သည် (Linux၊ Solaris၊ OSX၊ FreeBSD၊ 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"

ရှင်းရှင်းပြောရလျှင်၊ ကျွန်ုပ်သည် ကျွန်ုပ်၏ “အသိမိတ်ဆွေဟောင်း” ကို ချက်ချင်းမမှတ်မိပါ။ ထို့အပြင်၊ ပရောဂျက်ကို Elbrus တွင် အကြိမ်များစွာ စမ်းသပ်ခဲ့ပြီး Alt အပါအဝင် မတူညီသော ဖြန့်ဖြူးမှုများစွာအောက်တွင် ရှိနေသည်။ အမျိုးမျိုးသော compilers၊ GNU Make နှင့် bash ဗားရှင်းများ။ ဒါကြောင့် ငါ့အမှားကို ဒီမှာ မမြင်ချင်ဘူး။

ပြဿနာကို ပြန်လည်ဖန်တီးရန်နှင့်/သို့မဟုတ် ဖြစ်ပျက်နေသည့်အရာများကို နားလည်ရန်ကြိုးစားသောအခါတွင် ပို၍ထူးဆန်းသောအရာများ ပေါ်ပေါက်လာသည်။
Command line စာလုံးပေါင်း-

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

တခါတရံ အပိုစာသားတွေ ထွက်လာလိမ့်မယ်၊ မဟုတ်ဘူးလား... မကြာခဏဆိုသလို ရွေးချယ်စရာတစ်ခုက အချိန်အတော်ကြာအောင် ကပ်ထားတတ်ပေမယ့် ပိုရှည်သွားရင်တော့ နှစ်ခုစလုံးကို အမြဲရတတ်ပါတယ်။

သင်တန်း၏, strace ငါတို့အရာရာ! ပြီးတော့ strace tirade ကိုရိုက်ထည့်လိုက်ပေမယ့် Enter နှိပ်ဖို့ အချိန်မရလို့ သူငယ်ချင်းဟောင်း Mr. Heisenbug နဲ့ developer တွေကို မှတ်မိခဲ့တယ်၊ compiler ကျွန်တော်ကိုယ်တိုင် လွန်ခဲ့တဲ့ ၂၅ နှစ်၊ လွမ်းဆွတ်... ဝမ်းနည်းပြီး ဒီမှတ်စုလေးရေးဖို့ ဆုံးဖြတ်လိုက်တယ် 😉

စကားမစပ် ကိုယ်ကိုကိုယ် လေးစားတာမျိုး ကြိုက်တယ်။ Heisenbugကြမ်းပြင်၊ strace မျိုးပွားရန် မကြိုက်ပါ။

ဒါဆို ဘာဖြစ်နေတာလဲ?

  • အသုံးဝင်သည် head တောင်းဆိုထားသည့် လိုင်းအရေအတွက်ကို ဖတ်ပြီးသည်နှင့် ချန်နယ်ကို ဖတ်ရှုနေသည့် ချန်နယ်ကို ပိတ်ရန် (သို့မဟုတ် ယင်းအစား အတင်းအကျပ်ခိုင်းစေခြင်း) တွင် အခွင့်အရေးရှိသည်။
  • ဒေတာထုတ်ပေးတဲ့ ပရိုဂရမ်ရေးသူ (ဒီကိစ္စမှာ cc) နိုင် လိုင်းများစွာနှင့် print ထုတ်ပါ။ အခမဲ့ ခေါ်ဆိုမှုများစွာဖြင့် ပြုလုပ်ပါ။ 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 သေးငယ်သော (လိုင်းများစွာ) နှင့် ချန်နယ်ကြားခံစနစ် (OS ≥512K အများစုတွင် 64 bytes မှ ≈4K အထိ) တွင် အံဝင်ခွင်ကျရှိသည်။ မဟုတ်ရင် ပြဿနာက ပြန်ဖြစ်လာနိုင်တယ်။

မှန်ကန်စွာ စီမံဆောင်ရွက်ပုံ EPIPE နှင့် အခြားသော အသံသွင်းအမှားများ ?

မှန်ကန်သောဖြေရှင်းချက်တစ်ခုမျှမရှိသော်လည်း ရိုးရှင်းသောအကြံပြုချက်များရှိသည်။

  • EPIPE လိုအပ် စီမံဆောင်ရွက်ရမည်။ ခိုင်မာမှုလိုအပ်သော ဒေတာကို ထုတ်သည့်အခါ (ထွက်ပေါက်အခြေအနေတွင် ထင်ဟပ်စေသည်)။ ဥပမာအားဖြင့်၊ archivers သို့မဟုတ် backup utilities များလည်ပတ်နေစဉ်။
  • EPIPE လျစ်လျူရှုတာ ပိုကောင်းပါတယ်။ အချက်အလက်နှင့် အရန်စာများကို ပြသသည့်အခါ။ ဥပမာအားဖြင့်၊ ရွေးချယ်စရာများပေါ်တွင် အချက်အလက်ပြသသည့်အခါ --help သို့မဟုတ် --version.
  • ကုဒ်ကို တီထွင်နေပါက ပိုက်လိုင်းကို အရင်သုံးနိုင်သည်။ | headထိုအခါ EPIPE လျစ်လျူရှုခြင်းသည် ပိုကောင်းသည်၊ မဟုတ်ပါက ထွက်ပေါက်အခြေအနေတွင် စီမံဆောင်ရွက်ပြီး ထင်ဟပ်ပြခြင်းက ပိုကောင်းပါသည်။

အသင်းတွေကို ကျေးဇူးတင်ကြောင်း ဖော်ပြဖို့ ဒီအခွင့်အရေးကို ရယူချင်ပါတယ်။ MCST и altlinux ကြီးမြတ်သောအကျိုးဖြစ်ထွန်းသောအလုပ်အတွက်။ မင်းရဲ့ဆုံးဖြတ်ချက်က အံ့သြစရာပဲ။
အဲဒါကို စောင့်ပါ ရဲဘော်ရဲဘက်တွေ၊ ဆောင်းဦးတွင်အစည်းအဝေးများ!

Спасибо berez အမှားများနှင့် အမှားများကို ပြုပြင်ရန်အတွက်။
KDPV ထံမှ Georgy A

source: www.habr.com

မှတ်ချက် Add