Heisenbug amháin eile anuas ar an crogall

Heisenbug amháin eile anuas ar an crogall

$> set -o pipefail

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

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

Anseo fortune clár coinníollach gan exit(rand()).

An féidir leat a mhíniú? cad atá mícheart anseo?

Digression lyrical-stairiúil

Chuir mé aithne ar an Heisenbug seo ar dtús ceathrú céad bliain ó shin. Ansin le haghaidh an gheata i FaxNET bhí sé riachtanach a chruthú roinnt fóntais trí píopaí "seiceálaithe imeartha" faoi FreeBSD. De réir mar a bhíothas ag súil leis, mheas mé féin mar ríomhchláraitheoir chun cinn agus go leor taithí acu. Mar sin, bhí sé ar intinn agam gach rud a dhéanamh chomh cúramach agus chomh cúramach agus is féidir, ag tabhairt aird ar leith ar láimhseáil earráidí ...

Chuir an taithí a bhí agam roimhe seo ag déileáil le fabhtanna i sendmail agus uucp/uupc le mo dhíograis i “láimhseáil críochnúil earráidí.” Níl aon phointe ag dul isteach i sonraí an scéil sin, ach bhí mé ag streachailt leis an Heisenbug seo ar feadh dhá sheachtain ar feadh 10-14 uair an chloig. Cuimhníodh mar sin, agus inné stop an sean-aithne seo le cuairt a thabhairt arís.

TL; DR Freagra

Fóntais head Is féidir dún an cainéal ó fortune ag an am céanna a luaithe a léann sé an chéad líne. Dá fortune aschuireann sé níos mó ná líne amháin, ansin an glao comhfhreagrach write() seolfaidh sé earráid ar ais nó tuairisceoidh sé go bhfuil níos lú beart á aschur ná mar a iarrtar. Ina dhiaidh sin, scríofa le láimhseáil earráideach cúramach fortune tá an ceart aige an cás seo a léiriú ina stádas scoir. Ansin mar gheall ar a shuiteáil set -o pipefail oibreoidh || echo "Вы проиграли".

Mar sin féin, head ní féidir é a dhéanamh in am dhúnadh roimh fortune críochnóidh an t-aschur sonraí. Ansin oibreoidh sé && echo "Повезло!".

I gceann de mo chuid inniu GNUMakefile tá a leithéid ann blúire:

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

Aistrithe go daonna

Tá sé coitianta anseo le haghaidh GNU Déan и Eabhrac ar an mbealach tiomsaitheoir ag baint úsáide as an rogha --version fiafraíonn sé cé hé, agus mura dtacaítear leis an rogha, cuirtear stub isteach "Bain úsáid as tiomsaitheoir comhoiriúnach le GCC nó CLANG".

cosúil le pláta coire le fáil in áit ar bith. Bhí an chuma air san áit seo i bhfad ó shin agus d'oibrigh sé go foirfe i ngach áit (Linux, Solaris, OSX, FreeBSD, WSL srl). Ach inné i altlinux ar an ardán Elbrus 2000 (E2K) Thug mé faoi deara:

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

Le fírinne, níor aithin mé láithreach mo shean “aithne.” Thairis sin, tá an tionscadal a thástáil go minic cheana féin ar Elbrus agus faoi go leor dáiltí éagsúla, lena n-áirítear Alt. Le tiomsaitheoirí éagsúla, leaganacha de GNU Make agus bash. Mar sin, níor theastaigh uaim mo bhotún a fheiceáil anseo.

Nuair a bhíothas ag iarraidh an fhadhb a atáirgeadh agus/nó a thuiscint cad a bhí ar siúl, thosaigh rudaí níos aisteach ag tarlú.
Litriú líne ordaithe:

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

Ó am go chéile chuirfeadh sé téacs breise ar fáil, mar sin ní... Is minic go gcloífeadh ceann de na roghanna ar feadh i bhfad, ach dá bpocáil tú níos faide, fuair tú an dá cheann i gcónaí!

Ar ndóigh, strace ár gach rud! Agus strace tirade clóscríofa agam, ach gan an t-am agam Enter a bhrú, d'aithin mé mo sheanchara an tUasal Heisenbug, agus na forbróirí tiomsaitheoir mé féin 25 bliain ó shin, Nostalgia… Agus chinn mé a bheith brónach agus scríobh an nóta seo 😉

Dála an scéil, cosúil le haon féin-urramú Heisenbug, faoi strace fearr gan a atáirgeadh.

Mar sin, cad atá ar siúl?

  • Fóntais head an bhfuil sé de cheart aige (nó in áit sin, fiú amháin) an cainéal atá á léamh a dhúnadh a luaithe a léann sé an líon línte a iarrtar.
  • An clár-scríbhneoir a ghineann sonraí (sa chás seo cc) Is féidir línte iolracha a phriontáil agus saor é seo a dhéanamh trí ghlaonna iolracha write().
  • Más rud é beidh am ag an léitheoir an cainéal ar a thaobh a dhúnadh roimh dheireadh an taifeadta ar thaobh an scríbhneora, ansin gheobhaidh an scríbhneoir earráid.
  • Clár scríbhneoir i dteideal neamhaird a dhéanamh ar an earráid scríobh cainéal agus léirigh i do chód críochnaithe í.
  • Mar gheall ar a shuiteáil set -o pipefail beidh an cód críochnaithe píblíne neamh-nialas (earráideach) má tá an toradh neamh-nialas ó eilimint amháin ar a laghad, agus ansin oibreoidh sé || echo "Please use GCC or CLANG compatible compiler".

D’fhéadfadh go mbeadh éagsúlachtaí ag brath ar an gcaoi a n-oibríonn an clár scríbhneoir le comharthaí. Mar shampla, féadfaidh an clár deireadh a chur go neamhghnách (le stádas foirceanta neamh-nialais/earráid a ghiniúint go huathoibríoch), nó write() tabharfaidh sé ar ais an toradh ó scríobh níos lú beart ná mar a iarrtar agus socraithe errno = EPIPE.

Cé atá ciontach?

Sa chás cur síos beagán de gach rud. Earráid á láimhseáil i cc (lcc:1.23.20:Sep—4-2019:e2k-v3-linux) Níl iomarcach. I go leor cásanna tá sé níos fearr a bheith cúramach, cé go nochtar lochtanna tobanna i bpláta coire atá deartha le haghaidh iompar traidisiúnta.

Cad le déanamh?

Mícheart:

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

Ceart:

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

    Anseo, láimhseálfaidh an t-ateangaire ordaithe píopa a dhúnadh go luath agus é ag freastal ar an bpíblíne neadaithe ("laistigh" de na lúibíní). Dá réir sin, más rud é fortune tuairisceoidh earráid i scríbhinn chuig cainéal dúnta sa stádas, ansin an t-aschur || echo "Ошибка" ní bhfaighidh sé áit ar bith, ós rud é go bhfuil an cainéal dúnta cheana féin.

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

    Seo é an áirgiúlacht cat feidhmíonn sé mar thaise toisc go ndéanann sé neamhaird den earráid EPIPE ar tharraingt siar. Is leor é seo do chonclúid anois fortune beag (roinnt línte) agus luíonn sé sa mhaolán cainéal (ó 512 bytes go ≈64K, sa chuid is mó OS ≥4K). Seachas sin féadfaidh an fhadhb filleadh.

Conas a phróiseáil i gceart EPIPE agus earráidí taifeadta eile?

Níl aon réiteach ceart amháin ann, ach tá moltaí simplí ann:

  • EPIPE riachtanach Ní mór a phróiseáil (agus léirithe sa stádas scoir) agus sonraí á n-aschur a éilíonn sláine. Mar shampla, le linn oibriú cartlannaithe nó fóntais cúltaca.
  • EPIPE níos fearr neamhaird a dhéanamh nuair a bhíonn faisnéis agus teachtaireachtaí cúnta á dtaispeáint. Mar shampla, nuair a thaispeánfar faisnéis faoi roghanna --help--version.
  • Más féidir an cód atá á fhorbairt a úsáid i bpíblíne roimhe seo | headansin EPIPE Is fearr neamhaird a dhéanamh, ar shlí eile is fearr é a phróiseáil agus a léiriú sa stádas scoir.

Ba mhaith liom an deis seo a thapú chun mo bhuíochas a chur in iúl do na foirne MCST и altlinux le haghaidh obair tháirgiúil iontach. Tá do chinneadh iontach!
Coinnigh sé suas Camaráidí, suas cruinnithe sa titim!

Go raibh maith agat beirz chun typos agus earráidí a cheartú.
KDPV ó George A.

Foinse: will.com

Add a comment