Siji maneh Heisenbug liwat baya

Siji maneh Heisenbug liwat baya

$> set -o pipefail

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

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

iku fortune program kondisional tanpa exit(rand()).

Apa sampeyan bisa nerangake? ana apa ing kene?

Digression liris-historis

Aku pisanan dadi kenalan karo Heisenbug iki seprapat abad kepungkur. Banjur kanggo gateway ing FaxNET perlu kanggo nggawe sawetara keperluan liwat pipa "playing checkers" ing FreeBSD. Kaya sing dikarepake, aku nganggep aku minangka programer sing maju lan cukup berpengalaman. Mulane, aku arep nindakake kabeh kanthi ati-ati lan kanthi ati-ati sabisa, menehi perhatian khusus kanggo penanganan kesalahan ...

Pengalamanku sadurunge nangani kewan omo ing sendmail lan uucp/upc ditambahake kanggo ketekunan "penanganan kesalahan sing lengkap." Ora ana gunane nyilem menyang rincian crita kasebut, nanging aku berjuang karo Heisenbug iki sajrone rong minggu suwene 10-14 jam. Mula dieling-eling, wingi kenalan tuwa iki mampir dolan maneh.

TL; DR Jawaban

Utilitas head bisa nutup saluran saka fortune langsung sanalika dheweke maca baris pisanan. Yen fortune output luwih saka siji baris, banjur telpon cocog write() bakal ngasilake kesalahan utawa laporan yen bita luwih sithik tinimbang sing dijaluk. Ing siji, ditulis kanthi ati-ati kesalahan penanganan fortune nduweni hak kanggo nggambarake kahanan iki ing status metu sawijining. Banjur amarga instalasi set -o pipefail bakal bisa || echo "Π’Ρ‹ ΠΏΡ€ΠΎΠΈΠ³Ρ€Π°Π»ΠΈ".

Nanging, head bisa uga ora teka ing wektu cedhak sadurunge fortune bakal rampung output data. Banjur bakal bisa && echo "ПовСзло!".

Ing salah sawijining dina iki GNUMakefile ana kuwi pecahan:

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

Diterjemahake menyang manungsa

Iku umum kene kanggo GNU Gawe ΠΈ bash ing cara compiler nggunakake pilihan --version iku takon sapa iku, lan yen pilihan ora didhukung, banjur stub dipasang "Gunakake kompiler sing kompatibel karo GCC utawa CLANG".

Kaya boilerplate bisa ditemokake ing ngendi wae. Muncul ing panggonan iki wis suwe lan bisa digunakake kanthi sampurna ing endi wae (Linux, Solaris, OSX, FreeBSD, WSL lsp). Nanging wingi ing altlinux ing platform Elbrus 2000 (E2K) Aku weruh:

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

Terus terang, aku ora langsung ngerteni "kenalan" lawasku. Kajaba iku, proyek kasebut wis diuji kaping pirang-pirang ing Elbrus lan ing macem-macem distribusi, kalebu Alt. Kanthi macem-macem kompiler, versi GNU Make lan bash. Mulane, aku ora pengin ndeleng kesalahanku ing kene.

Nalika nyoba ngasilake masalah lan / utawa ngerti apa sing kedadeyan, kedadeyan sing luwih aneh.
Ejaan baris perintah:

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

Saben-saben bakal ngasilake teks ekstra, banjur ora ... Asring salah siji opsi bakal tetep kanggo dangu, nanging yen sampeyan poked maneh, sampeyan tansah entuk loro!

Mesthi, strace kabeh kita! Lan wis ngetik tirade strace, nanging ora duwe wektu kanggo pencet Ketik, Aku dikenali kanca lawas Pak Heisenbug, lan pangembang. compiler aku 25 taun kepungkur, Nostalgia… Lan aku mutusake kanggo sedih lan nulis cathetan iki πŸ˜‰

Miturut cara, kaya sembarang ajining dhiri Heisenbug, miturut strace luwih seneng ora reproduksi.

Dadi apa sing kedadeyan?

  • Utilitas head nduweni hak (utawa luwih, malah dipeksa) kanggo nutup saluran sing diwaca sanalika maca nomer garis sing dijaluk.
  • Penulis program sing ngasilake data (ing kasus iki cc) bisa print sawetara garis lan gratis nindakake iki liwat sawetara telpon write().
  • yen maca bakal duwe wektu kanggo nutup saluran ing sisih sadurunge mburi rekaman ing sisih penulis, banjur penulis bakal nampa kesalahan.
  • Program panulis duwe hak loro nglirwakake kesalahan nulis saluran lan nggambarake ing kode completion Panjenengan.
  • Amarga instalasi set -o pipefail kode completion pipeline bakal non-zero (erroneous) yen asil non-zero saka paling siji unsur, lan banjur bakal bisa || echo "Please use GCC or CLANG compatible compiler".

Bisa uga ana variasi gumantung carane program panulis bisa nganggo sinyal. Contone, program kasebut bisa mandheg kanthi ora normal (kanthi nggawe status terminasi non-nol/error otomatis), utawa write() bakal ngasilake asil nulis bita luwih sithik tinimbang sing dijaluk lan disetel errno = EPIPE.

Sapa sing disalahake?

Ing kasus sing diterangake sethitik kabeh. Kesalahan nangani ing cc (lcc:1.23.20:Sepβ€”4-2019:e2k-v3-linux) ora keluwih. Ing pirang-pirang kasus, luwih apik kanggo salah ing sisih ati-ati, sanajan iki mbukak cacat dadakan ing boilerplate sing dirancang kanggo prilaku tradisional.

Apa aku kudu?

Salah:

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

Bener:

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

    Ing kene, penutupan awal pipa bakal ditangani dening juru printah nalika nglayani pipa bersarang ("ing" kurung). Patut, yen fortune bakal laporan kesalahan ing nulis kanggo saluran ditutup ing status, banjur output || echo "Ошибка" ora bakal tekan ngendi wae, amarga saluran kasebut wis ditutup.

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

    Punika sarana cat tumindak minangka damper amarga nglirwakake kesalahan EPIPE nalika mundur. Iki cukup kanggo kesimpulan saiki fortune cilik (sawetara garis) lan mathuk ing buffer saluran (saka 512 bait kanggo β‰ˆ64K, ing paling OS β‰₯4K). Yen ora masalah bisa bali.

Cara ngolah kanthi bener EPIPE lan kesalahan rekaman liyane?

Ora ana solusi sing bener, nanging ana rekomendasi sing gampang:

  • EPIPE dibutuhake kudu diproses (lan dibayangke ing status metu) nalika outputting data sing mbutuhake integritas. Contone, sajrone operasi arsip utawa utilitas serep.
  • EPIPE luwih becik digatekake nalika nampilake informasi lan pesen tambahan. Contone, nalika nampilake informasi babagan opsi --help utawa --version.
  • Yen kode sing dikembangake bisa digunakake ing pipa sadurunge | head, banjur EPIPE Iku luwih apik kanggo nglirwakake, yen ora, iku luwih apik kanggo proses lan nggambarake ing status metu.

Aku pengin njupuk kesempatan iki kanggo ngucapake matur nuwun marang tim MCST ΠΈ altlinux kanggo karya produktif gedhe. Tekadmu apik tenan!
Terusno Camarades, munggah rapat-rapat ing tiba!

Бпасибо beres kanggo mbenerake typo lan kesalahan.
KDPV saka Georgy A.

Source: www.habr.com

Add a comment