$> set -o pipefail
$> fortune | head -1 > /dev/null && echo "ΠΠΎΠ²Π΅Π·Π»ΠΎ!" || echo "ΠΡ ΠΏΡΠΎΠΈΠ³ΡΠ°Π»ΠΈ"
ΠΠΎΠ²Π΅Π·Π»ΠΎ!
$> fortune | head -1 > /dev/null && echo "ΠΠΎΠ²Π΅Π·Π»ΠΎ!" || echo "ΠΡ ΠΏΡΠΎΠΈΠ³ΡΠ°Π»ΠΈ"
ΠΡ ΠΏΡΠΎΠΈΠ³ΡΠ°Π»ΠΈ
Yma fortune
rhaglen amodol heb exit(rand())
.
Allwch chi esbonio? beth sy'n bod yma?
Digression telynegol-hanesyddol
Deuthum yn gyfarwydd Γ’'r Heisenbug hwn gyntaf chwarter canrif yn Γ΄l. Yna ar gyfer y porth yn FaxNET roedd angen creu sawl cyfleustodau trwy
Ychwanegodd fy mhrofiad blaenorol o ddelio Γ’ bygiau mewn sendmail ac uucp/uupc at fy niwydrwydd wrth βdrin gwallau trwyadl.β Nid oes diben plymio i fanylion y stori honno, ond bΓ»m yn cael trafferth gyda'r Heisenbug hwn am bythefnos am 10-14 awr. Felly, Cofiwyd, a ddoe arhosodd yr hen gydnabod hwn i ymweld eto.
TL; DR Ateb
Cyfleustodau head
Gall cau'r sianel o fortune
ar unwaith cyn gynted ag y darlleno y llinell gyntaf. Os fortune
yn allbynnu mwy nag un llinell, yna'r alwad gyfatebol write()
yn dychwelyd gwall neu'n adrodd bod llai o beit yn cael ei allbwn nag y gofynnwyd amdano. Yn ei dro, wedi'i ysgrifennu gan drin gwallau yn ofalus fortune
yr hawl i adlewyrchu'r sefyllfa hon yn ei statws ymadael. Yna oherwydd gosod set -o pipefail
bydd yn gweithio || echo "ΠΡ ΠΏΡΠΎΠΈΠ³ΡΠ°Π»ΠΈ"
.
Fodd bynnag, head
efallai na fydd yn ei wneud mewn pryd cau o'r blaen fortune
yn gorffen allbynnu data. Yna bydd yn gweithio && echo "ΠΠΎΠ²Π΅Π·Π»ΠΎ!"
.
Yn un o fy heddiw GNUMakefile
echo '#define MDBX_BUILD_COMPILER "$(shell set -o pipefail; $(CC) --version | head -1 || echo 'Please use GCC or CLANG compatible compiler')"'
Wedi'i gyfieithu i ddynol
Mae'n gyffredin yma am --version
mae'n gofyn pwy ydyw, ac os na chefnogir yr opsiwn, yna gosodir bonyn "Defnyddiwch casglwr cydnaws GCC neu CLANG".
Fel
#define MDBX_BUILD_COMPILER "lcc:1.23.20:Sep--4-2019:e2k-v3-linux Please use GCC or CLANG compatible compiler"
A dweud y gwir, wnes i ddim adnabod fy hen βgydnabod.β Ar ben hynny, mae'r prosiect eisoes wedi'i brofi sawl gwaith ar Elbrus ac o dan lawer o wahanol ddosbarthiadau, gan gynnwys Alt. Gyda chasglwyr amrywiol, fersiynau o GNU Make a bash. Felly, doeddwn i ddim eisiau gweld fy nghamgymeriad yma.
Wrth geisio atgynhyrchu'r broblem a/neu ddeall beth oedd yn digwydd, dechreuodd pethau rhyfeddach ddigwydd.
Sillafu llinell orchymyn:
echo "#define MDBX_BUILD_COMPILER '$(set -o pipefail; LC_ALL=C cc --version | head -1 || echo "Please use GCC or CLANG compatible compiler")'"
O bryd i'w gilydd byddai'n cynhyrchu testun ychwanegol, yna ddim... Yn aml byddai un o'r opsiynau yn aros am amser eithaf hir, ond pe byddech chi'n pocio'n hirach, roedd gennych chi'r ddau bob amser!
Wrth gwrs, strace
Gyda llaw, fel unrhyw hunan-barch strace
well ganddo beidio ag atgynhyrchu.
Felly beth sy'n mynd ymlaen?
- Cyfleustodau
head
Γ’'r hawl (neu yn hytrach yn cael ei orfodi hyd yn oed) i gau'r sianel sy'n cael ei darllen cyn gynted ag y bydd yn darllen y nifer o linellau y gofynnwyd amdanynt. - Ysgrifennwr y rhaglen cynhyrchu data (yn yr achos hwn
cc
) Gall argraffu llinellau lluosog a rhydd gwneud hyn trwy alwadau lluosogwrite()
. - Os bydd gan y darllenydd amser i gau'r sianel ar ei ochr cyn diwedd y recordio ar ochr yr awdur, yna bydd yr awdur yn derbyn gwall.
- Rhaglen awdur mae ganddo'r hawl mae'r ddau yn anwybyddu gwall ysgrifennu'r sianel ac yn ei adlewyrchu yn eich cod cwblhau.
- Oherwydd gosod
set -o pipefail
bydd cod cwblhau'r biblinell yn ddi-sero (gwallus) os yw'r canlyniad yn ddi-sero o un elfen o leiaf, ac yna bydd yn gweithio|| echo "Please use GCC or CLANG compatible compiler"
.
Efallai y bydd amrywiadau yn dibynnu ar sut mae'r rhaglen awdur yn gweithio gyda signalau. Er enghraifft, gall y rhaglen ddod i ben yn annormal (gyda chynhyrchu statws terfynu di-sero/gwall yn awtomatig), neu write()
yn dychwelyd canlyniad ysgrifennu llai o beit nag y gofynnwyd amdano ac a osodwyd errno = EPIPE
.
Pwy sydd ar fai?
Yn yr achos a ddisgrifir ychydig bach o bopeth. Gwall wrth drin yn cc
(lcc:1.23.20:Sepβ4-2019:e2k-v3-linux) ddim segur. Mewn llawer o achosion mae'n well bod yn ofalus, er bod hyn yn amlygu diffygion sydyn mewn plΓ’t boeler sydd wedi'i gynllunio ar gyfer ymddygiad traddodiadol.
Beth i'w wneud?
Anghywir:
fortune | head -1 && echo "ΠΠΎΠ²Π΅Π·Π»ΠΎ, Π½ΠΎ Π²Ρ ΡΠΈΡΠΊΡΠ΅ΡΠ΅!" || echo "WTF?"
Yn gywir:
-
(fortune && echo "Π£ΡΠΏΠ΅ΡΠ½ΠΎ" || echo "ΠΡΠΈΠ±ΠΊΠ°") | head -1
Yma, bydd cau pibell yn gynnar yn cael ei drin gan y cyfieithydd gorchymyn wrth wasanaethu'r biblinell nythu ("o fewn" y cromfachau). Yn unol Γ’ hynny, os
fortune
yn adrodd gwall yn ysgrifenedig i sianel gaeedig yn y statws, yna'r allbwn|| echo "ΠΡΠΈΠ±ΠΊΠ°"
ni fydd yn cyrraedd unrhyw le, gan fod y sianel eisoes ar gau. -
fortune | cat - | head -1 && echo "Π£ΡΠΏΠ΅ΡΠ½ΠΎ" || echo "ΠΡΠΈΠ±ΠΊΠ°"
Dyma'r cyfleustodau
cat
yn gweithredu fel damper oherwydd ei fod yn anwybyddu'r gwallEPIPE
wrth dynnu'n Γ΄l. Mae hyn yn ddigon am y tro casgliadfortune
bach (sawl llinell) ac yn ffitio yn y byffer sianel (o 512 beit i β64K, yn y rhan fwyaf o OS β₯4K). Fel arall, efallai y bydd y broblem yn dychwelyd.
Sut i brosesu'n gywir EPIPE
a gwallau cofnodi eraill?
Nid oes un ateb cywir, ond mae yna argymhellion syml:
EPIPE
yn ofynnol rhaid ei brosesu (ac a adlewyrchir yn y statws ymadael) wrth allbynnu data sy'n gofyn am gywirdeb. Er enghraifft, yn ystod gweithrediad archifwyr neu gyfleustodau wrth gefn.EPIPE
well anwybyddu wrth arddangos gwybodaeth a negeseuon ategol. Er enghraifft, wrth arddangos gwybodaeth am opsiynau--help
neu--version
.- Os gellir defnyddio'r cod sy'n cael ei ddatblygu ar y gweill o'r blaen
| head
, YnaEPIPE
Mae'n well anwybyddu, fel arall mae'n well prosesu a myfyrio yn y statws ymadael.
Hoffwn achub ar y cyfle hwn i fynegi fy niolch iβr timau
Daliwch ati Camaradau, i fyny
Diolch
KDPV oddi wrth
Ffynhonnell: hab.com