Wieħed Heisenbug aktar passat il-kukkudrill

Wieħed Heisenbug aktar passat il-kukkudrill

$> set -o pipefail

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

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

Hawnhekk fortune programm kondizzjonali mingħajr exit(rand()).

Tista' tispjega? x'hemm ħażin hawn?

Digressjoni lirika-storika

L-ewwel sirt familjari ma' dan il-Heisenbug kwart ta' seklu ilu. Imbagħad għall-portal f'FaxNET kien meħtieġ li jinħolqu diversi utilitajiet permezz pajpijiet "playing checkers" taħt FreeBSD. Kif mistenni, qisni lili nnifsi programmatur avvanzat u b'esperjenza pjuttost tajba. Għalhekk, kelli l-intenzjoni li nagħmel kollox bl-aktar mod bir-reqqa u bir-reqqa possibbli, billi nagħti attenzjoni speċjali lill-immaniġġjar tal-iżbalji...

L-esperjenza preċedenti tiegħi li nittratta l-bugs fis-sendmail u l-uucp/uupc żiedet mad-diliġenza tiegħi fl-"immaniġġjar bir-reqqa tal-iżbalji." M'hemm l-ebda skop li togħdos fid-dettalji ta 'dik l-istorja, iżda tħabtu ma' dan Heisenbug għal ġimgħatejn għal 10-14-il siegħa. Għalhekk, ġie mfakkar, u lbieraħ dan il-konoxxenza antik waqaf biex jerġa’ jżur.

TL;DR Tweġiba

Utilità head jista agħlaq il-kanal minn fortune f'daqqa malli jaqra l-ewwel linja. Jekk fortune joħroġ aktar minn linja waħda, imbagħad is-sejħa korrispondenti write() se jirritorna żball jew jirrapporta li jinħarġu inqas bytes milli mitlub. Min-naħa tagħhom, miktuba bl-immaniġġjar tal-iżbalji bir-reqqa fortune għandha d-dritt li tirrifletti din is-sitwazzjoni fl-istatus ta’ ħruġ tagħha. Imbagħad minħabba l-installazzjoni set -o pipefail se taħdem || echo "Вы проиграли".

Madankollu, head ma jistax jasal fil-ħin qrib qabel fortune se jispiċċa joħroġ id-data. Imbagħad se taħdem && echo "Повезло!".

F'wieħed mill-lum tiegħi GNUMakefile hemm tali framment:

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

Tradott fil-bniedem

Huwa komuni hawn għal GNU Make и bash bil-mod tal-kompilatur bl-użu tal-għażla --version tistaqsi min hu, u jekk l-għażla ma tkunx appoġġjata, imbagħad jiddaħħal stub "Jekk jogħġbok uża kompilatur kompatibbli GCC jew CLANG".

Simili boilerplate jistgħu jinstabu kullimkien. F'dan il-post deher ħafna żmien ilu u ħadmet perfettament kullimkien (Linux, Solaris, OSX, FreeBSD, WSL eċċ.). Iżda lbieraħ fil altlinux fuq il-pjattaforma Elbrus 2000 (E2K) Indunajt:

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

Franchement, ma għarafejtx mill-ewwel il-“konoxxenza” tiegħi. Barra minn hekk, il-proġett diġà ġie ttestjat ħafna drabi fuq Elbrus u taħt ħafna distribuzzjonijiet differenti, inkluż Alt. B'diversi kompilaturi, verżjonijiet ta' GNU Make u bash. Għalhekk, ma ridtx nara l-iżball tiegħi hawn.

Meta tipprova tirriproduċi l-problema u/jew tifhem x'kien qed jiġri, bdew iseħħu aktar affarijiet strambi.
Spell tal-linja tal-kmand:

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

Kultant kien jipproduċi test żejjed, allura le... Ħafna drabi waħda mill-għażliet kienet tibqa 'għal żmien pjuttost twil, imma jekk tpoġġi aktar, dejjem ikollok it-tnejn!

Of course, strace kollox tagħna! U wara li ttajpjat tirade strace, imma ma kellix ħin biex tagħfas Enter, għarafajt lill-ħabib antik tiegħi Sur Heisenbug, u lill-iżviluppaturi kompilatur jien stess 25 sena ilu, Nostalġija ... U ddeċidejt li nkun imdejjaq u nikteb din in-nota 😉

Mill-mod, bħal kull li jirrispetta lilu nnifsu Heisenbug, taħt strace jippreferi ma jirriproduċix.

Allura x'qed jiġri?

  • Utilità head għandu d-dritt (jew aħjar, huwa saħansitra sfurzat) li jagħlaq il-kanal li qed jinqara hekk kif jaqra n-numru ta’ linji mitlub.
  • Il-kittieb tal-programm li jiġġenera d-dejta (f'dan il-każ cc) jista istampa linji multipli u b'xejn tagħmel dan permezz ta' sejħiet multipli write().
  • Jekk il-qarrej ikollu ħin biex jagħlaq il-kanal fuq in-naħa tiegħu qabel it-tmiem tar-reġistrazzjoni fuq in-naħa tal-kittieb, allura l-kittieb jirċievi żball.
  • Programm tal-kittieb għandu d-dritt it-tnejn jinjoraw l-iżball tal-kitba tal-kanal u jirriflettuh fil-kodiċi tat-tlestija tiegħek.
  • Minħabba l-installazzjoni set -o pipefail il-kodiċi tat-tlestija tal-pipeline se jkun mhux żero (żbaljat) jekk ir-riżultat ikun mhux żero minn mill-inqas element wieħed, u mbagħad jaħdem || echo "Please use GCC or CLANG compatible compiler".

Jista 'jkun hemm varjazzjonijiet skond kif il-programm kittieb jaħdem mas-sinjali. Pereżempju, il-programm jista' jintemm b'mod anormali (b'ġenerazzjoni awtomatika ta' status ta' terminazzjoni mhux żero/żball), jew write() se jirritorna r-riżultat tal-kitba ta 'inqas bytes milli mitlub u ssettjat errno = EPIPE.

Min hu ħati?

Fil-każ deskritt ftit minn kollox. Immaniġġjar ta' żbalji fi cc (lcc:1.23.20:Sep—4-2019:e2k-v3-linux) mhux żejda. F'ħafna każijiet huwa aħjar li wieħed jiżbalja min-naħa tal-kawtela, għalkemm dan jesponi difetti f'daqqa f'boilerplate iddisinjat għal imġieba tradizzjonali.

X'għandek tagħmel?

Ħażin:

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

B'mod korrett:

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

    Hawnhekk, l-għeluq bikri ta 'pajp se jiġi mmaniġġjat mill-interpretu tal-kmand meta jservi l-pipeline nested ("ġewwa" il-parentesi). Għaldaqstant, jekk fortune se tirrapporta żball bil-miktub lil kanal magħluq fl-istatus, imbagħad l-output || echo "Ошибка" ma jasal imkien, peress li l-kanal huwa diġà magħluq.

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

    Hawn l-utilità cat jaġixxi bħala umidifikatur minħabba li jinjora l-iżball EPIPE mal-irtirar. Dan huwa biżżejjed għalissa konklużjoni fortune żgħar (diversi linji) u jidħlu fil-buffer tal-kanal (minn 512 bytes għal ≈64K, fil-biċċa l-kbira tal-OS ≥4K). Inkella l-problema tista 'tirritorna.

Kif tipproċessa b'mod korrett EPIPE u żbalji oħra ta' reġistrazzjoni?

M'hemm l-ebda soluzzjoni tajba waħda, iżda hemm rakkomandazzjonijiet sempliċi:

  • EPIPE meħtieġa għandhom jiġu pproċessati (u rifless fl-istatus tal-ħruġ) meta toħroġ data li teħtieġ integrità. Per eżempju, waqt l-operazzjoni ta 'arkivji jew utilitajiet backup.
  • EPIPE aħjar li tinjora meta turi informazzjoni u messaġġi awżiljarji. Per eżempju, meta turi informazzjoni dwar l-għażliet --help jew --version.
  • Jekk il-kodiċi li qed jiġi żviluppat jista 'jintuża f'pipeline qabel | head, Imbagħad EPIPE Huwa aħjar li tinjora, inkella huwa aħjar li tipproċessa u tirrifletti fl-istatus tal-ħruġ.

Nixtieq nieħu din l-opportunità biex nesprimi l-gratitudni tiegħi lit-timijiet MCST и altlinux għal xogħol produttiv kbir. Id-determinazzjoni tiegħek hija tal-għaġeb!
Żomm hekk Camarades, up laqgħat fil-ħarifa!

Grazzi berez għall-korrezzjoni ta’ typos u żbalji.
KDPV minn Georgy A.

Sors: www.habr.com

Żid kumment