Heisenbug eile seachad air a’ chrogall

Heisenbug eile seachad air a’ chrogall

$> set -o pipefail

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

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

tha e fortune Prògram gun chùmhnant a exit(rand()).

An urrainn dhut mìneachadh? dè tha ceàrr an seo?

Digression liriceach-eachdraidheil

Fhuair mi eòlas air an Heisenbug seo an toiseach cairteal de cheud bliadhna air ais. An uairsin airson a’ gheata ann am FaxNET bha e riatanach grunn ghoireasan a chruthachadh tro phìob "cluich checkers" fo FreeBSD. Mar a bhiodh dùil, bha mi gam mheas fhèin mar phrògramadair adhartach agus eòlach. Mar sin, bha mi an dùil a h-uile càil a dhèanamh cho faiceallach agus cho faiceallach sa ghabhas, a’ toirt aire shònraichte do làimhseachadh mhearachdan ...

Chuir an t-eòlas a bh’ agam roimhe air a bhith a’ dèiligeadh ri biastagan ann an sendmail agus uucp/uupc ris an dìcheall agam ann an “làimhseachadh mhearachdan mionaideach.” Chan eil feum air dàibheadh ​​​​a-steach do mhion-fhiosrachadh na sgeòil sin, ach bha mi a’ strì leis an Heisenbug seo airson dà sheachdain airson 10-14 uairean. Mar sin, chaidh a chuimhneachadh, agus an-dè stad an seann neach-eòlais seo gus tadhal a-rithist.

TL; DR Freagair

Goireasach head urrainn dùin an sianal bho fortune сразу cho luath ‘s a leughas e a’ chiad loidhne. Ma tha fortune a’ toirt a-mach barrachd air aon loidhne, an uairsin a’ ghairm fhreagarrach write() tillidh e mearachd no aithrisidh e gu bheil nas lugha de bytes air an toirt a-mach na chaidh iarraidh. Ann an tionndadh, sgrìobhte le làimhseachadh mhearachdan faiceallach fortune tha còir aige an suidheachadh seo a nochdadh san inbhe fàgail aige. An uairsin air sgàth an stàladh set -o pipefail obraichidh || echo "Вы проиграли".

Ach, head is dòcha nach dèan e ann an ùine dùin roimhe fortune crìoch air cur a-mach dàta. An uairsin obraichidh e && echo "Повезло!".

Ann am fear de na tha agam an-diugh GNUMakefile tha aon ann criomag:

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

Air eadar-theangachadh gu duine

Tha e cumanta an seo airson Dèan GNU и bash anns an dòigh compiler a 'cleachdadh an roghainn --version bidh e a’ faighneachd cò e, agus mura h-eil taic ris an roghainn, thèid stub a chuir a-steach msgstr "Feuch an cleachd thu inneal-cruinneachaidh GCC no CLANG".

mar clàr-goileadair gheibhear an àite sam bith. Nochd e san àite seo o chionn fhada agus dh’ obraich e gu foirfe anns a h-uile àite (Linux, Solaris, OSX, FreeBSD, WSL msaa). Ach an-dè a-staigh altlinux air an àrd-ùrlar Elbrus 2000 (E2K) mhothaich mi:

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

Gu fìrinneach, cha do dh’ aithnich mi sa bhad mo sheann “luchd-eòlais.” A bharrachd air an sin, chaidh am pròiseact a dhearbhadh iomadh uair air Elbrus agus fo iomadh sgaoileadh eadar-dhealaichte, Alt nam measg. Le diofar luchd-cruinneachaidh, dreachan de GNU Make and bash. Mar sin, cha robh mi airson mo mhearachd fhaicinn an seo.

Nuair a bha iad a’ feuchainn ris an duilgheadas ath-riochdachadh agus/no a’ tuigsinn dè bha a’ dol, thòisich rudan na bu neònach a’ tachairt.
Litreachas loidhne-àithne:

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

Bho àm gu àm bhiodh e a’ toirt a-mach teacsa a bharrachd, mar sin chan... Gu math tric bhiodh aon de na roghainnean a’ cumail airson ùine mhòr, ach nam biodh tu a’ putadh na b’ fhaide, bhiodh an dà chuid agad an-còmhnaidh!

Gu dearbh, strace ar n-uile rud! Agus an dèidh dhomh strace tirade a thaipeadh, ach gun ùine agam Enter a bhrùthadh, dh’ aithnich mi mo sheann charaid Mgr Heisenbug, agus an luchd-leasachaidh fear-cruinneachaidh mi fhìn 25 bliadhna air ais, Nostalgie… Agus chuir mi romham a bhith brònach agus an nota seo a sgrìobhadh 😉

Co-dhiù, mar fèin-spèis sam bith Heisenbug, fo strace b’ fheàrr leis gun a bhith a’ gintinn.

Mar sin dè tha dol?

  • Goireasach head aig a bheil còir (no an àite, eadhon air èigneachadh) an sianal a tha ga leughadh a dhùnadh cho luath ‘s a leughas e an àireamh de loidhnichean a chaidh iarraidh.
  • Sgrìobhadair a’ phrògraim gineadh dàta (sa chùis seo cc) urrainn clò-bhuail iomadh loidhne agus saor dèan seo tro ioma-ghairm write().
  • ma bidh ùine aig an leughadair an t-sianal air a thaobh a dhùnadh ro dheireadh a’ chlàradh air taobh an sgrìobhadair, agus an uairsin gheibh an sgrìobhadair mearachd.
  • Prògram sgrìobhadair airidh air an dà chuid seachain mearachd sgrìobhaidh an t-seanail agus ga nochdadh sa chòd crìochnachaidh agad.
  • Air sgàth stàladh set -o pipefail bidh an còd crìochnachaidh loidhne-phìoban neo-neoni (mearachdach) ma tha an toradh neo-neoni bho co-dhiù aon eileamaid, agus an uairsin obraichidh e || echo "Please use GCC or CLANG compatible compiler".

Faodaidh caochlaidhean a bhith ann a rèir mar a tha am prògram sgrìobhadair ag obair le comharran. Mar eisimpleir, faodaidh am prògram crìochnachadh gu h-annasach (le gineadh fèin-ghluasadach de inbhe crìochnachaidh neo-neoni / mearachd), no write() tillidh e toradh sgrìobhaidh nas lugha de bytes na chaidh iarraidh agus a chaidh a shuidheachadh errno = EPIPE.

Cò as coireach?

Anns a 'chùis a chaidh a mhìneachadh beagan dhen a h-uile càil. Mearachd ann an làimhseachadh cc (lcc:1.23.20:Sep—4-2019:e2k-v3-linux) nach eil gun fheum. Ann an iomadh cùis tha e nas fheàrr a bhith faiceallach, ged a tha seo a 'nochdadh lochdan gu h-obann ann am boilerplate a chaidh a dhealbhadh airson giùlan traidiseanta.

Dè bu chòir dhomh a dhèanamh?

Ceàrr:

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

Ceart:

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

    An seo, thèid dùnadh pìoba tràth a làimhseachadh leis an eadar-theangair àithne nuair a bhios e a 'frithealadh na loidhne-phìoban neadachaidh ("taobh a-staigh" na brathan). A rèir sin, ma tha fortune bheir e cunntas air mearachd ann an sgrìobhadh gu seanal dùinte san inbhe, an uairsin an toradh || echo "Ошибка" chan fhaigh e àite sam bith, leis gu bheil an sianal dùinte mu thràth.

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

    Seo an goireas cat ag obair mar damper oir tha e a’ seachnadh a’ mhearachd EPIPE nuair a tharraing air ais. Tha seo gu leòr airson a-nis co-dhùnadh fortune beag (grunn loidhnichean) agus a’ freagairt air bufair an t-seanail (bho 512 bytes gu ≈64K, anns a’ mhòr-chuid de OS ≥4K). Mur eil, faodaidh an duilgheadas tilleadh.

Mar a làimhsicheas tu gu ceart EPIPE agus mearachdan clàraidh eile?

Chan eil aon fhuasgladh ceart ann, ach tha molaidhean sìmplidh ann:

  • EPIPE a dhìth feumar a phròiseasadh (agus air a nochdadh san inbhe fàgail) nuair a thathar a’ cur a-mach dàta a dh’ fheumas ionracas. Mar eisimpleir, rè obrachadh thasglannan no goireasan cùl-taic.
  • EPIPE b'fhearr gun dearmad nuair a sheallas tu fiosrachadh agus teachdaireachdan taiceil. Mar eisimpleir, nuair a sheallas tu fiosrachadh mu roghainnean --help no --version.
  • Ma tha an còd a thathar a 'leasachadh faodar a chleachdadh ann an loidhne-phìoban roimhe | head, an uairsin EPIPE Tha e nas fheàrr dearmad a dhèanamh, air neo tha e nas fheàrr a phròiseasadh agus a mheòrachadh san inbhe fàgail.

Bu mhath leam an cothrom seo a ghabhail mo thaing a thoirt dha na sgiobaidhean MCST и altlinux airson obair mhòr chinneasach. Tha do mhisneachd iongantach!
Cùm e suas Cammarades, suas coinneamhan as t-fhoghar!

Спасибо beir airson typos agus mearachdan a cheartachadh.
KDPV bho Seòras A.

Source: www.habr.com

Cuir beachd ann