Usa pa ka Heisenbug nga milabay sa buaya

Usa pa ka Heisenbug nga milabay sa buaya

$> set -o pipefail

$> fortune | head -1 > /dev/null && echo "ПовСзло!" || echo "Π’Ρ‹ ΠΏΡ€ΠΎΠΈΠ³Ρ€Π°Π»ΠΈ"
ПовСзло!

$> fortune | head -1 > /dev/null && echo "ПовСзло!" || echo "Π’Ρ‹ ΠΏΡ€ΠΎΠΈΠ³Ρ€Π°Π»ΠΈ"
Π’Ρ‹ ΠΏΡ€ΠΎΠΈΠ³Ρ€Π°Π»ΠΈ

kini mao ang fortune conditional program nga wala exit(rand()).

Mahimo ba nimo ipasabut? unsay problema dinhi?

Lyrical-historical digression

Una nakong nahibal-an kini nga Heisenbug usa ka quarter sa usa ka siglo ang milabay. Unya alang sa ganghaan sa FaxNET gikinahanglan nga maghimo daghang mga gamit pinaagi sa mga tubo "pagdula og mga tseke" ubos sa FreeBSD. Sama sa gipaabut, giisip nako ang akong kaugalingon nga usa ka advanced ug medyo eksperyensiyado nga programmer. Busa, gituyo nako nga buhaton ang tanan nga maampingon ug mabinantayon kutob sa mahimo, nga naghatag espesyal nga pagtagad sa pagdumala sa sayup...

Ang akong kanhing kasinatian sa pag-atubang sa mga bug sa sendmail ug uucp/upc nakadugang sa akong kakugi sa "hingpit nga pagdumala sa sayup." Wala’y kapuslanan ang pag-dive sa mga detalye sa kana nga istorya, apan nakigbisog ako niining Heisenbug sulod sa duha ka semana sulod sa 10-14 ka oras. Busa, kini nahinumduman, ug kagahapon kining tigulang nga kaila mihunong aron sa pagbisita pag-usab.

TL; DR Tubag

Gamit head mahimo isira ang channel gikan sa fortune diha-diha pagkabasa niya sa unang linya. Kung fortune nagpagawas og labaw sa usa ka linya, dayon ang katugbang nga tawag write() ibalik ang usa ka sayup o ireport nga mas gamay nga mga byte ang na-output kaysa gihangyo. Sa baylo, gisulat uban ang mabinantayon nga pagdumala sa sayup fortune adunay katungod sa pagpakita niini nga sitwasyon sa iyang exit status. Unya tungod sa pag-instalar set -o pipefail motrabaho || echo "Π’Ρ‹ ΠΏΡ€ΠΎΠΈΠ³Ρ€Π°Π»ΠΈ".

Hinuon, head mahimong dili makaabot sa oras hapit na fortune mahuman ang pag-output sa datos. Unya kini molihok && echo "ПовСзло!".

Sa usa sa akong karon GNUMakefile adunay usa tipik:

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

Gihubad ngadto sa tawo

Kini komon dinhi alang sa GNU Himua ΠΈ bash sa paagi sa compiler gamit ang opsyon --version kini nangutana kon kinsa siya, ug kung ang opsyon dili suportado, unya usa ka stub ang gisal-ut "Palihug gamita ang GCC o CLANG compatible compiler".

Ingon boilerplate makita bisan asa. Kini nagpakita niini nga dapit sa dugay na nga panahon ug nagtrabaho nga hingpit bisan asa (Linux, Solaris, OSX, FreeBSD, WSL ug uban pa). Apan kagahapon sa altlinux sa plataporma Elbrus 2000 (E2K) Nakabantay ko:

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

Sa prangka, wala dayon nako mailhi ang akong daan nga "kaila." Dugang pa, ang proyekto nasulayan na sa daghang mga higayon sa Elbrus ug sa ilawom sa daghang lainlaing mga pag-apod-apod, lakip ang Alt. Uban sa lain-laing mga compiler, mga bersyon sa GNU Make ug bash. Busa, dili ko gusto nga makita ang akong sayop dinhi.

Kung gisulayan nga kopyahon ang problema ug / o masabtan kung unsa ang nanghitabo, daghang katingad-an nga mga butang ang nagsugod nga nahitabo.
Spell sa 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")'"

Matag karon ug unya makapatungha kini ug dugang nga teksto, unya dili... Kasagaran ang usa sa mga kapilian magpabilin sa dugay nga panahon, apan kung magdugay ka, kanunay nimong makuha ang duha!

Siyempre, strace atong tanan! Ug sa pag-type sa usa ka strace tirade, apan wala’y oras sa pagpindot sa Enter, nahibal-an nako ang akong tigulang nga higala nga si Mr. Heisenbug, ug ang mga nag-develop. tigkompiler akong kaugalingon 25 ka tuig na ang milabay, Nostalgie… Ug nakahukom ko nga maguol ug isulat kini nga nota πŸ˜‰

Pinaagi sa dalan, sama sa bisan unsa nga pagtahud sa kaugalingon Heisenbug, ilalum strace mas gusto nga dili magpadaghan.

Busa unsa ang nahitabo?

  • Gamit head adunay katungod (o napugos pa gani) sa pagsira sa channel nga gibasa sa diha nga kini nagbasa sa gihangyo nga gidaghanon sa mga linya.
  • Ang data-generating program-writer (sa kini nga kaso cc) mahimo pag-imprinta og daghang linya ug libre buhata kini pinaagi sa daghang mga tawag write().
  • kon ang magbabasa adunay panahon sa pagsira sa channel sa iyang kilid sa dili pa matapos ang pagrekord sa kiliran sa magsusulat, unya ang magsusulat makadawat og sayop.
  • Programa sa magsusulat adunay katungod sa pareho nga wala magtagad sa channel sa pagsulat nga sayup ug ipakita kini sa imong kodigo sa pagkompleto.
  • Tungod sa pag-instalar set -o pipefail ang code sa pagkompleto sa pipeline mahimong non-zero (sayop) kung ang resulta dili zero gikan sa labing menos usa ka elemento, ug unya kini molihok || echo "Please use GCC or CLANG compatible compiler".

Mahimong adunay mga kalainan depende kung giunsa ang programa sa magsusulat nagtrabaho sa mga signal. Pananglitan, ang programa mahimong mohunong sa abnormal nga paagi (nga adunay awtomatik nga paghimo sa usa ka non-zero/error termination status), o write() ibalik ang resulta sa pagsulat og mas gamay nga byte kay sa gihangyo ug gitakda errno = EPIPE.

Kinsa may sad-an?

Sa gihulagway nga kaso gamay sa tanan. Sayop sa pagdumala cc (lcc:1.23.20:Sepβ€”4-2019:e2k-v3-linux) dili kadaghanon. Sa daghang mga kaso mas maayo nga masayop sa bahin sa pag-amping, bisan kung kini nagpadayag sa kalit nga mga sayup sa usa ka boilerplate nga gidisenyo alang sa tradisyonal nga pamatasan.

Unsay akong buhaton?

Sayop:

fortune | head -1 && echo "ПовСзло, Π½ΠΎ Π²Ρ‹ рискуСтС!" || echo "WTF?"

Husto nga:

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

    Dinhi, ang sayo nga pagsira sa usa ka tubo pagadumalahon sa command interpreter sa pag-alagad sa nested pipeline ("sulod" sa mga parentesis). Subay niini, kung fortune i-report ang usa ka sayup sa pagsulat sa usa ka sirado nga channel sa status, dayon ang output || echo "Ошибка" dili kini makuha bisan asa, tungod kay sirado na ang channel.

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

    Ania ang utility cat naglihok ingon nga usa ka damper tungod kay kini wala magtagad sa sayup EPIPE sa pag-withdraw. Kini igo na alang sa karon nga konklusyon fortune gamay (pila ka linya) ug mohaum sa channel buffer (gikan sa 512 bytes ngadto sa β‰ˆ64K, sa kadaghanan sa OS β‰₯4K). Kung dili ang problema mahimong mobalik.

Sa unsa nga paagi sa pagproseso sa husto EPIPE ug uban pang mga sayup sa pagrekord?

Walay usa nga husto nga solusyon, apan adunay yano nga mga rekomendasyon:

  • EPIPE gikinahanglan kinahanglan nga iproseso (ug gipakita sa exit status) sa dihang nagpagawas sa datos nga nagkinahanglan sa integridad. Pananglitan, sa panahon sa operasyon sa mga archiver o backup utilities.
  • EPIPE mas maayo nga ibaliwala sa pagpakita sa impormasyon ug auxiliary nga mga mensahe. Pananglitan, sa pagpakita sa impormasyon sa mga kapilian --help o --version.
  • Kung ang code nga gihimo mahimong magamit sa usa ka pipeline kaniadto | head, dayon EPIPE Mas maayo nga ibaliwala, kung dili, mas maayo nga iproseso ug ipakita sa exit status.

Gusto nakong pahimuslan kini nga higayon aron ipahayag ang akong pasalamat sa mga team MCST ΠΈ altlinux para sa dakong produktibo nga trabaho. Ang imong determinasyon talagsaon!
Ipadayon kini mga higala, pataas mga miting sa tingdagdag!

Бпасибо berez para sa pagtul-id sa mga typo ug mga sayop.
KDPV gikan sa Georgy A.

Source: www.habr.com

Idugang sa usa ka comment