Cerita rakyat tentang programmer dan insinyur (bagian 1)





Ini adalah kumpulan cerita dari Internet tentang bagaimana bug terkadang memiliki manifestasi yang luar biasa. Mungkin Anda juga punya cerita untuk diceritakan.



Alergi mobil terhadap es krim vanila



Sebuah cerita untuk para insinyur yang memahami bahwa yang sudah jelas tidak selalu menjadi solusi, dan bahwa betapapun tidak masuk akal fakta tersebut, itu adalah fakta. Divisi Pontiac General Motors Corporation menerima keluhan:



, , , . : . , , , , . Pontiac, . , , , . , . , , : « Pontiac, - , , , ?».


Seperti yang bisa Anda bayangkan, presiden divisi itu skeptis dengan surat itu. Namun, untuk berjaga-jaga, mengirim seorang insinyur untuk memeriksa. Dia terkejut bertemu dengan seorang pria kaya dan terpelajar yang tinggal di daerah yang indah. Mereka setuju untuk bertemu tepat setelah makan malam untuk pergi ke toko es krim bersama. Itu vanilla malam itu, dan ketika mereka kembali ke mobil, itu tidak mau menyala.



Insinyur itu datang tiga malam lagi. Pertama kali es krim adalah coklat. Mobil mulai menyala. Kedua kalinya ada es krim stroberi. Mobil mulai menyala. Pada malam ketiga, dia meminta vanilla. Mobil tidak mau hidup.



Dengan alasan yang bijak, insinyur tersebut menolak untuk percaya pada alergi mobil terhadap es krim vanilla. Oleh karena itu, saya setuju dengan pemilik mobil bahwa dia akan melanjutkan kunjungannya sampai dia menemukan solusi untuk masalah tersebut. Dan di sepanjang jalan, dia mulai membuat catatan: dia menuliskan semua informasi, waktu hari, jenis bensin, waktu kedatangan dan pengembalian dari toko, dll.



Segera, insinyur tersebut menyadari bahwa pemilik mobil menghabiskan lebih sedikit waktu untuk membeli es krim vanila. Alasannya adalah tata letak produk di toko. Es krim vanila adalah yang paling populer dan disimpan di freezer terpisah di depan toko agar lebih mudah ditemukan. Dan semua varietas lainnya ada di belakang toko, dan butuh lebih banyak waktu untuk menemukan varietas yang tepat dan membayar.



Sekarang pertanyaannya adalah untuk insinyurnya: mengapa mobil tidak dapat dihidupkan, jika lebih sedikit waktu berlalu sejak mesin dimatikan? Karena masalahnya adalah waktu, bukan es krim vanila, insinyur itu dengan cepat menemukan jawabannya: itu adalah kunci gas. Itu muncul setiap malam, tetapi ketika pemilik mobil menghabiskan lebih banyak waktu untuk mencari es krim, mesin punya waktu untuk cukup dingin dan mulai dengan tenang. Dan ketika lelaki itu membeli es krim vanilla, mesin masih terlalu panas dan busi tidak sempat larut.



Moral: Bahkan masalah yang benar-benar gila terkadang bisa menjadi nyata.



Crash Bandicoot



Sangat menyakitkan untuk mengalami ini. Sebagai seorang programmer, Anda terbiasa menyalahkan kode Anda terlebih dahulu, kedua, ketiga ... dan di suatu tempat di sepuluh ribu Anda menyalahkan compiler. Dan bahkan menurunkan daftar, Anda sudah menyalahkan peralatan tersebut.



Berikut adalah cerita saya tentang bug perangkat keras.



Untuk game Crash Bandicoot, saya menulis kode untuk dimuat dan disimpan ke kartu memori. Untuk pengembang game yang benar-benar mandiri, ini seperti berjalan di taman: Saya pikir pekerjaan itu akan memakan waktu beberapa hari. Namun, sebagai hasilnya, saya men-debug kode tersebut selama enam minggu. Saya memecahkan masalah lain di sepanjang jalan, tetapi setiap beberapa hari saya kembali ke kode ini selama beberapa jam. Itu sangat menyakitkan.



Gejalanya terlihat seperti ini: ketika Anda menyimpan permainan saat ini dan mengakses kartu memori, hampir selalu semuanya berjalan dengan baik ... Tetapi terkadang operasi baca atau tulis diselesaikan dengan batas waktu tanpa alasan yang jelas. Rekaman singkat sering kali merusak kartu memori. Ketika seorang pemain mencoba menyelamatkan, dia tidak hanya gagal menyelamatkan, tetapi juga menghancurkan peta. Panekuk.



Setelah beberapa saat, produser kami di Sony, Connie Bus, mulai panik. Kami tidak dapat mengirimkan game dengan bug ini, dan setelah enam minggu saya tidak mengerti apa penyebab masalah ini. Melalui Connie, kami menghubungi pengembang PS1 lainnya: apakah ada yang mengalami masalah serupa? Tidak. Tidak ada yang punya masalah dengan kartu memori.



Jika Anda tidak memiliki ide untuk men-debug, hampir satu-satunya pendekatan adalah "bagi dan taklukkan": Anda menghapus semakin banyak kode dari program yang salah hingga terdapat fragmen yang relatif kecil, yang masih menyebabkan masalah. Artinya, Anda memotong program sepotong demi sepotong sampai bagian yang mengandung bug tetap ada.



Tapi intinya adalah, sangat sulit untuk memotong bagian dari video game. Bagaimana cara menjalankannya jika Anda menghapus kode emulasi gravitasi? Atau menggambar karakter?



Oleh karena itu, Anda harus mengganti seluruh modul dengan stub yang berpura-pura melakukan sesuatu yang berguna, tetapi sebenarnya melakukan sesuatu yang sangat sederhana dan tidak mengandung kesalahan. Kami harus menulis kruk seperti itu untuk membuat permainan berhasil. Ini adalah proses yang lambat dan menyakitkan.



Singkatnya, saya berhasil. Saya menghapus lebih banyak potongan kode sampai ada kode awal yang mengatur sistem untuk memulai permainan, menginisialisasi peralatan untuk rendering, dll. Tentu saja, pada tahap ini, saya tidak dapat membuat menu save and load, karena saya harus membuat stub untuk semua kode grafis. Tetapi saya bisa berpura-pura menjadi pengguna yang menggunakan layar simpan dan muat (tidak terlihat) dan meminta untuk menyimpan lalu menulis ke kartu memori.



Akibatnya, saya mendapatkan potongan kecil kode yang masih mengalami masalah yang disebutkan di atas - tetapi sejauh ini hal itu terjadi secara acak! Sebagian besar waktu semuanya bekerja dengan baik, tetapi kadang-kadang macet. Saya menghapus hampir semua kode permainan, tetapi bug masih hidup. Ini membingungkan: kode yang tersisa tidak benar-benar berguna.



Pada titik tertentu, mungkin pada pukul tiga pagi, sebuah pikiran muncul di benak saya. Operasi baca dan tulis (I / O) mengasumsikan waktu yang tepat. Saat bekerja dengan hard disk, kartu memori atau modul Bluetooth, kode tingkat rendah yang bertanggung jawab untuk membaca dan menulis melakukannya sesuai dengan pulsa jam.



Dengan bantuan jam, perangkat yang tidak terhubung langsung ke prosesor disinkronkan dengan kode yang dapat dieksekusi di prosesor. Jam menentukan baud rate - baud rate. Jika ada kebingungan dengan pengaturan waktu, maka baik perangkat keras atau lunaknya, atau keduanya, juga ikut bingung. Dan ini sangat buruk, karena datanya bisa rusak.



Bagaimana jika sesuatu dalam kode kami membingungkan pengaturan waktu? Saya memeriksa semua yang terkait dengan ini dalam kode program pengujian dan memperhatikan bahwa kami mengatur timer yang dapat diprogram di PS1 ke frekuensi 1 kHz (1000 siklus per detik). Ini cukup banyak, secara default berjalan pada 100 Hz saat set-top box dimulai. Dan sebagian besar game menggunakan frekuensi ini.



Andy, pengembang game, mengatur timer ke 1 kHz agar pergerakan dihitung lebih akurat. Andy cenderung berlebihan, dan jika kita meniru gravitasi, maka kita melakukannya seakurat mungkin!



Tetapi bagaimana jika mempercepat pengatur waktu mempengaruhi waktu keseluruhan program, dan karenanya jam yang menyesuaikan laju baud untuk kartu memori?



Saya telah mengomentari kode pengatur waktu. Kesalahan tidak pernah terjadi lagi. Tetapi ini tidak berarti bahwa kami memperbaikinya, karena kegagalan terjadi secara acak. Bagaimana jika saya baru saja beruntung?



Beberapa hari kemudian, saya bereksperimen dengan program pengujian lagi. Bug itu tidak terulang. Saya kembali ke basis kode game lengkap dan mengubah kode simpan dan muat sehingga pengatur waktu yang dapat diprogram disetel ulang ke nilai aslinya (100Hz) sebelum mengakses kartu memori, dan kemudian kembali ke 1kHz lagi. Tidak ada lagi tabrakan.



Tapi kenapa ini bisa terjadi?



Saya kembali ke program tes lagi. Saya mencoba menemukan beberapa keteraturan dalam terjadinya kesalahan dengan timer 1 kHz. Akhirnya saya perhatikan bahwa kesalahan terjadi ketika seseorang bermain dengan pengontrol PS1. Karena saya jarang melakukan ini sendiri - mengapa saya memerlukan pengontrol saat menguji simpan dan muat kode? - kemudian saya tidak melihat ketergantungan ini. Tetapi suatu hari salah satu artis kami menunggu saya untuk menyelesaikan pengujian - saya mungkin mengutuk saat itu - dan dengan gugup memutar pengontrol di tangannya. Sebuah kesalahan telah terjadi. "Tunggu apa ?! Nah, lakukan lagi! "



Ketika saya menyadari bahwa kedua peristiwa ini saling berhubungan, saya dapat dengan mudah mereproduksi kesalahan: Saya mulai menulis ke kartu memori, memindahkan pengontrol, merusak kartu memori. Bagi saya itu tampak seperti bug perangkat keras.



Saya pergi ke Connie dan menceritakan tentang penemuan saya. Dia menyampaikan informasi tersebut ke salah satu insinyur yang merancang PS1. "Tidak mungkin," jawabnya, "itu tidak mungkin masalah perangkat keras." Saya meminta Connie untuk berbicara dengan kami.



Insinyur itu menelepon saya dan kami berdebat dengannya dalam bahasa Inggris yang rusak dan bahasa Jepang saya yang (sangat) rusak. Akhirnya saya berkata, "Izinkan saya mengirimkan program pengujian 30 baris saya di mana gerakan pengontrol menyebabkan bug." Dia setuju. Mengatakan itu hanya buang-buang waktu dan dia sangat sibuk mengerjakan proyek baru, tetapi dia akan menyerah karena kami adalah pengembang yang sangat penting bagi Sony. Saya membersihkan program tes saya dan mengirimkannya kepadanya.



Malam berikutnya (kami berada di Los Angeles, dan dia di Tokyo) dia menelepon saya dan meminta maaf dengan malu-malu. Itu masalah perangkat keras.



Saya tidak tahu persis apa bug itu, tetapi dari apa yang saya dengar di kantor pusat Sony, mengatur timer ke nilai yang cukup tinggi akan mengganggu komponen pada motherboard di dekat kristal timer. Salah satunya adalah pengontrol baud rate kartu memori, yang juga mengatur baud rate untuk pengontrol. Saya bukan seorang insinyur, jadi saya mungkin bingung tentang sesuatu.



Namun intinya adalah terjadi gangguan antar komponen pada motherboard. Dan ketika secara bersamaan mentransmisikan data melalui port pengontrol dan port kartu memori dengan timer yang beroperasi pada frekuensi 1 kHz, bit hilang, data hilang, dan kartu rusak.



Sapi yang buruk



Pada 1980-an, mentor saya Sergei menulis perangkat lunak untuk CM-1800, tiruan PDP-11 Soviet. Komputer mikro ini baru saja dipasang di stasiun kereta api dekat Sverdlovsk, pusat transportasi penting di Uni Soviet. Sistem baru ini dirancang untuk pengarahan gerbong dan arus kargo. Tapi ternyata itu adalah bug yang mengganggu yang menyebabkan crash dan crash secara acak. Jatuh selalu terjadi saat seseorang pulang pada malam hari. Tetapi meskipun penyelidikan cermat keesokan harinya, komputer bekerja dengan benar dengan semua tes manual dan otomatis. Ini biasanya menunjukkan kondisi balapan atau beberapa bug konkurensi lainnya yang memanifestasikan dirinya dalam kondisi tertentu. Bosan dengan telepon larut malam, Sergei memutuskan untuk menyelesaikannya, dan pertama-tama, untuk memahami kondisi apa di halaman marshalling yang menyebabkan kerusakan komputer.



Pertama, dia mengumpulkan statistik pada semua kejadian jatuh yang tidak dapat dijelaskan dan membuat grafik berdasarkan tanggal dan waktu. Polanya jelas. Setelah menonton selama beberapa hari lagi, Sergey menyadari bahwa dia dapat dengan mudah memprediksi waktu kegagalan sistem di masa depan.



Dia segera mengetahui bahwa gangguan hanya terjadi ketika stasiun sedang menyortir gerobak ternak dari Ukraina utara dan Rusia barat ke rumah jagal terdekat. Ini sendiri aneh, karena rumah jagal dipasok oleh peternakan yang jauh lebih dekat di Kazakhstan.



Pembangkit listrik tenaga nuklir Chernobyl meledak pada tahun 1986, dan ledakan radioaktif membuat daerah sekitarnya tidak dapat dihuni. Area luas di Ukraina utara, Belarusia, dan Rusia barat telah terkontaminasi. Karena mencurigai adanya radiasi tingkat tinggi pada mobil yang tiba, Sergei mengembangkan metode untuk menguji teori ini. Penduduk dilarang memiliki dosimeter, jadi Sergei meletakkan beberapa orang militer di stasiun kereta api. Setelah beberapa kali minum vodka, dia berhasil meyakinkan prajurit itu untuk mengukur tingkat radiasi di salah satu mobil yang mencurigakan. Ternyata levelnya beberapa kali lebih tinggi dari nilai biasanya.



Tidak hanya ternak memancarkan radiasi yang kuat, levelnya juga sangat tinggi sehingga menyebabkan hilangnya bit secara tidak sengaja dalam memori CM-1800, yang berada di gedung sebelah stasiun.



Ada kekurangan makanan di Uni Soviet, dan pihak berwenang memutuskan untuk mencampur daging "Chernobyl" dengan daging dari daerah lain di negara itu. Ini memungkinkan untuk mengurangi tingkat radioaktivitas secara keseluruhan tanpa membuang sumber daya yang berharga. Setelah mengetahui hal ini, Sergei segera mengisi dokumen emigrasi. Dan jatuhnya komputer berhenti dengan sendirinya ketika tingkat radiasi menurun seiring waktu.



Melalui pipa



Solusi Movietech pernah membuat perangkat lunak untuk bioskop untuk tiket, tiket dan manajemen umum. Versi DOS dari aplikasi andalannya telah cukup populer dengan rantai teater kecil dan menengah di Amerika Utara. Jadi, tidak mengherankan bahwa ketika versi Windows 95 diumumkan, terintegrasi dengan layar sentuh terbaru dan kios swalayan, dan dilengkapi dengan semua jenis alat pelaporan, versi ini dengan cepat menjadi populer juga. Sebagian besar waktu, pembaruan berjalan dengan lancar. Staf TI di lapangan memasang perangkat keras baru, memindahkan data, dan bisnis berlanjut. Kecuali jika tidak berlanjut. Ketika ini terjadi, perusahaan mengirim James, yang dijuluki "The Cleaner".



Meskipun julukan ini mengacu pada tipe jahat, pembersih hanyalah kombinasi dari instruktur, penginstal, dan jack of all trade. James dapat menghabiskan beberapa hari di tempat klien meletakkan semua komponen bersama-sama, dan kemudian selama beberapa hari dia mengajari staf bagaimana menggunakan sistem baru, memperbaiki masalah perangkat keras yang mungkin timbul, dan benar-benar membantu perangkat lunak melewati periode formatifnya.



Oleh karena itu, tidak mengherankan jika pada jam-jam sibuk seperti ini, James datang ke kantor pada pagi hari, dan tidak sempat menjangkau mejanya, ketika disambut oleh bosnya yang dipenuhi dengan kafein di atas normal.



“Saya khawatir Anda harus pergi ke Annapolis di Nova Scotia secepat mungkin. Seluruh sistem mereka mati, dan setelah semalaman bekerja sama dengan teknisi mereka, kami tidak tahu apa yang terjadi. Sepertinya server mengalami kegagalan jaringan. Tetapi hanya setelah sistem bekerja selama beberapa menit.



- Mereka tidak kembali ke sistem lama? - James menjawab dengan cukup serius, meskipun dalam pikirannya dia melebarkan matanya karena terkejut.



- Persis: spesialis TI mereka "mengubah prioritas" dan dia memutuskan untuk keluar dengan server lama mereka. James, mereka telah menginstal sistem di enam situs dan baru saja membayar untuk dukungan premium, dan bisnis mereka sekarang berjalan di tahun 1950-an.



James menegakkan tubuh sedikit.



- Ini masalah lain. Oke, mari kita mulai.



Sesampainya di Annapolis, hal pertama yang dilakukannya adalah menemukan bioskop pertama kliennya yang bermasalah. Pada peta yang diambil di bandara, semuanya tampak layak, tetapi lingkungan sekitar alamat yang diinginkan tampak mencurigakan. Bukan ghetto, tapi mengingatkan pada film noir. Saat James parkir di tepi jalan di tengah, seorang pelacur mendekatinya. Mengingat luasnya Annapolis, kemungkinan besar itu satu-satunya di seluruh kota. Penampilannya langsung mengingatkan pada karakter terkenal yang menawarkan seks demi uang di layar lebar. Tidak, bukan tentang Julia Roberts, tapi tentang Jon Voight [ sedikit tentang film "Midnight Cowboy" - kira-kira. per. ].



Setelah mengirim pelacur pulang, James pergi ke bioskop. Lingkungan sudah menjadi lebih baik, tapi tetap saja kesannya tercipta kumuh. Bukan karena James terlalu khawatir. Dia sudah pernah ke tempat-tempat jorok. Dan ini adalah Kanada, di mana bahkan para perampok cukup sopan untuk mengucapkan terima kasih setelah mereka mengambil dompet Anda.



Pintu samping bioskop berada di gang lembap. James pergi ke pintu dan mengetuk. Segera dia berderit dan membuka sedikit.



- Apakah kamu seorang pembersih? Suara serak datang dari dalam.



“Ya, ini aku… Aku datang untuk memperbaiki semuanya.



James masuk ke lobi bioskop. Mungkin karena tidak ada pilihan lain, staf mulai mengeluarkan tiket kertas kepada pengunjung. Ini membuat pelaporan keuangan menjadi sulit, apalagi detail yang lebih menarik. Namun staf menyapa James dengan lega dan segera membawanya ke ruang server.



Pada pandangan pertama, semuanya beres. James masuk ke server dan memeriksa tempat-tempat mencurigakan yang biasa. Tidak masalah. Namun, sebagai tindakan pencegahan, James mematikan server, mengganti NIC, dan mengembalikan sistem. Dia langsung mulai bekerja secara penuh. Staf mulai menjual tiket lagi.



James menelepon Mark dan melaporkan situasinya. Tidak sulit untuk berasumsi bahwa James mungkin ingin berlama-lama di sini dan melihat apakah sesuatu yang tidak terduga terjadi. Dia menuruni tangga dan mulai menanyai staf tentang apa yang terjadi. Jelas sistem telah berhenti bekerja. Mereka mematikannya dan berhasil. Tapi setelah 10 menit, sistemnya mati.



Tepat pada saat itu sesuatu yang serupa terjadi. Tiba-tiba, sistem tiket mulai memberikan kesalahan. Staf itu menghela napas dan mengambil tiket kertas itu, dan James bergegas ke ruang server. Semuanya tampak bagus dengan server.



Lalu salah satu karyawan masuk.



- Sistem bekerja kembali.



James bingung karena dia tidak melakukan apa-apa. Lebih tepatnya, tidak ada yang bisa membuat sistem bekerja. Dia keluar, mengangkat telepon, dan menelepon tim dukungan perusahaannya. Segera karyawan yang sama memasuki ruang server.



- Sistemnya bohong.



James melirik server. Pola yang menarik dan akrab dari bentuk-bentuk warna-warni menari di layar - pipa yang meliuk dan terjalin secara acak. Kita semua pernah melihat screensaver ini. Itu disajikan dengan indah dan benar-benar terhipnotis.





James menekan tombol dan polanya menghilang. Dia bergegas ke kantor tiket dan dalam perjalanan bertemu dengan karyawan yang kembali padanya.



- Sistem bekerja kembali.



Jika Anda bisa membuat telapak tangan secara mental, maka itulah yang dilakukan James. Screen saver. Ini menggunakan OpenGL. Dan karena itu, selama operasi, itu menghabiskan semua sumber daya prosesor server. Akibatnya, setiap permintaan ke server habis waktu.



James kembali ke ruang server, masuk dan mengganti screensaver pipa yang indah dengan layar kosong. Artinya, alih-alih screensaver yang menghabiskan 100% sumber daya prosesor, saya menginstal yang lain yang tidak menghabiskan sumber daya. Kemudian saya menunggu 10 menit untuk memeriksa tebakan saya.



Ketika James tiba di bioskop berikutnya, dia bertanya-tanya bagaimana menjelaskan kepada supervisornya bahwa dia baru saja terbang sejauh 800 km untuk mematikan screensaver.



Crash pada fase bulan tertentu



Kisah nyata. Pernah ada bug perangkat lunak yang bergantung pada fase bulan. Ada sedikit subrutin yang biasa digunakan di berbagai program MIT untuk menghitung perkiraan fase bulan yang sebenarnya. GLS membangun subrutin ini ke dalam program LISP yang mengeluarkan string dengan cap waktu hampir 80 karakter saat menulis file. Sangat jarang baris pertama pesan terlalu panjang dan berlanjut ke baris berikutnya. Dan ketika program kemudian membaca file ini, itu terkutuk. Panjang baris pertama tergantung pada tanggal dan waktu yang tepat serta lamanya spesifikasi fase pada saat stempel waktu dicetak. Artinya, bug secara harfiah bergantung pada fase bulan!



Edisi makalah pertama dari Jargon File(Steele-1983) berisi contoh string seperti itu yang mengarah ke bug yang dijelaskan, tetapi kompositor "memperbaikinya". Sejak itu telah digambarkan sebagai "bug fase bulan".



Namun, berhati-hatilah dengan asumsi. Beberapa tahun yang lalu, para insinyur di CERN (Pusat Penelitian Nuklir Eropa) mengalami kesalahan dalam eksperimen yang dilakukan di Large Electron-Positron Collider. Karena komputer secara aktif memproses sejumlah besar data yang dihasilkan oleh perangkat ini sebelum menunjukkan hasilnya kepada para ilmuwan, banyak yang berasumsi bahwa perangkat lunak tersebut entah bagaimana sensitif terhadap fase bulan. Beberapa insinyur yang putus asa mengungkap kebenaran. Kesalahan tersebut terjadi karena perubahan kecil pada geometri cincin sepanjang 27 km akibat deformasi Bumi selama perjalanan Bulan! Kisah ini memasuki cerita rakyat fisikawan sebagai "balas dendam Newton pada fisika partikel" dan contoh hubungan antara hukum fisika tertua dan paling sederhana dengan konsep ilmiah paling maju.



Membilas toilet menghentikan kereta



Bug perangkat keras terbaik yang pernah saya dengar ada di kereta berkecepatan tinggi di Prancis. Bug menyebabkan pengereman darurat kereta, tetapi hanya jika ada penumpang di dalamnya. Dalam setiap kasus, kereta dihentikan dari layanan, diperiksa, tetapi tidak ada yang ditemukan. Kemudian dia dikirim kembali ke garis, dan dia segera berhenti secara tidak normal.



Dalam salah satu pemeriksaan, seorang insinyur yang bepergian dengan kereta pergi ke toilet. Segera hilang setelah itu sendiri, BOOM! Pemberhentian darurat.



Insinyur menghubungi pengemudi dan bertanya:



- Apa yang Anda lakukan sebelum pengereman?



- Nah, saya memperlambat saat turun ...



Itu aneh, karena selama berjalan normal kereta melambat di lereng puluhan kali. Kereta terus berjalan, dan pada saat turun berikutnya pengemudi memperingatkan:



- Saya akan memperlambat.



Tidak ada yang terjadi.



- Apa yang kamu lakukan dengan pengereman terakhir? - tanya sopirnya.



- Nah ... Aku di toilet ...



- Kalau begitu, pergilah ke toilet dan lakukan apa yang kamu lakukan saat kita turun lagi!



Insinyur itu pergi ke toilet, dan ketika pengemudi memperingatkan: "Saya sedang mengerem," dia menyiram air. Tentu saja kereta langsung berhenti.



Sekarang mereka dapat mereproduksi masalahnya dan perlu menemukan penyebabnya.



Setelah dua menit, mereka memperhatikan bahwa kabel remote control untuk pengereman mesin (kereta memiliki satu mesin di kedua ujungnya) telah diputus dari dinding kabinet listrik dan diletakkan di relai yang mengontrol solenoid colokan toilet ... Saat relai menyala, hal itu mengganggu kabel rem, dan sistem perlindungan tabrakan mencakup pengereman darurat.



Pintu gerbang yang membenci FORTRAN



Beberapa bulan yang lalu kami memperhatikan bahwa koneksi jaringan di daratan [ini di Hawaii] menjadi sangat, sangat lambat. Itu bisa berlangsung 10-15 menit dan kemudian tiba-tiba muncul kembali. Setelah beberapa saat, seorang rekan saya mengeluh kepada saya bahwa koneksi jaringan di daratan yang tidak bekerja sama sekali. Dia memiliki beberapa kode FORTRAN yang perlu disalin ke mesin di daratan, tetapi kode itu tidak berfungsi karena "jaringan tidak bertahan cukup lama untuk menyelesaikan pengunduhan FTP".



Ya, ternyata kegagalan jaringan terjadi ketika seorang kolega mencoba melakukan FTP file sumber FORTRAN ke komputer di daratan. Kami mencoba mengarsipkan file: kemudian disalin secara diam-diam (tetapi tidak ada unpacker pada mesin target, jadi masalah tidak terpecahkan). Akhirnya, kami "membagi" kode FORTRAN menjadi potongan-potongan yang sangat kecil dan mengirimkannya satu per satu. Sebagian besar fragmen disalin tanpa masalah, tetapi beberapa di antaranya tidak berfungsi, atau berhasil setelah beberapa kali percobaan.



Setelah memeriksa fragmen masalah, kami menemukan bahwa mereka memiliki kesamaan: semuanya berisi blok komentar yang dimulai dan diakhiri dengan baris yang terdiri dari huruf besar C (sebagai rekan lebih suka berkomentar di FORTRAN). Kami mengirim email ke daratan utama ke spesialis jaringan dan meminta bantuan. Tentu saja, mereka ingin melihat contoh file kami yang tidak dapat dikirim melalui FTP ... tetapi surat kami tidak sampai ke mereka. Akhirnya, kami mendapatkan deskripsi sederhana tentang seperti apa file yang tidak diteruskan itu. Berhasil :) [Berani saya menambahkan di sini contoh dari salah satu komentar bermasalah di FORTRAN? Mungkin tidak sepadan!]



Pada akhirnya kami berhasil mengetahuinya. Gerbang baru baru saja dipasang antara bagian kampus kami dan jaringan daratan. Dia mengalami kesulitan BESAR untuk mentransmisikan paket yang berisi duplikat C huruf besar! Hanya beberapa dari paket ini yang dapat mengambil semua sumber daya gateway dan mencegah sebagian besar paket lain menerobos. Kami mengeluh kepada produsen gateway ... dan mereka memberi tahu kami: "Oh, ya, Anda mengalami bug C duplikat! Kami sudah tahu tentang dia. " Pada akhirnya, kami menyelesaikan masalah dengan membeli gateway baru dari pabrikan lain (untuk membela yang pertama, saya akan mengatakan bahwa ketidakmampuan untuk mentransfer program ke FORTRAN dapat menjadi keuntungan bagi seseorang!).



Masa-masa sulit



Beberapa tahun yang lalu, saat mengerjakan sistem Perl ETL yang dirancang untuk mengurangi biaya uji klinis Tahap 3, saya perlu memproses sekitar 40.000 tanggal. Dua di antaranya tidak lulus ujian. Ini tidak terlalu mengganggu saya, karena tanggal-tanggal ini diambil dari data yang diberikan oleh klien, yang seringkali, katakanlah, mengejutkan. Tapi ketika saya cek data awal, ternyata tanggal tersebut adalah 1 Januari 2011 dan 1 Januari 2007. Saya kira bug itu ada di program yang baru saya tulis, tapi ternyata sudah berumur 30 tahun. Ini mungkin terdengar misterius bagi mereka yang tidak terbiasa dengan ekosistem perangkat lunak. Karena keputusan lama oleh perusahaan lain untuk menghasilkan uang, klien saya membayar saya untuk memperbaiki bug yang secara tidak sengaja diperkenalkan oleh satu perusahaan dan yang lain dengan sengaja. Agar Anda mengerti tentang apa ini,Saya perlu memberi tahu Anda tentang perusahaan yang menambahkan fitur yang menjadi bug akibatnya, serta beberapa peristiwa aneh lainnya yang berkontribusi pada bug misterius yang saya perbaiki.



Di masa lalu yang indah, komputer Apple terkadang secara spontan mengatur ulang tanggalnya menjadi 1 Januari 1904. Alasannya sederhana: "jam sistem" bertenaga baterai digunakan untuk melacak tanggal dan waktu. Apa yang terjadi saat baterai habis? Komputer mulai melacak tanggal dengan jumlah detik sejak permulaan era. Zaman berarti tanggal asli referensi, dan untuk Macintosh tanggal 1 Januari 1904. Dan setelah baterainya mati, tanggal saat ini disetel ulang ke tanggal yang ditentukan. Tapi kenapa ini bisa terjadi?



Sebelumnya, Apple menggunakan 32 bit untuk menyimpan jumlah detik dari tanggal aslinya. Satu bit dapat menyimpan satu dari dua nilai - 1 atau 0. Dua bit dapat menyimpan satu dari empat nilai: 00, 01, 10, 11. Tiga bit - satu nilai dari delapan: 000, 001, 010, 011, 100, 101, 110, 111, dll. Dan 32 dapat menyimpan salah satu dari 2 32 nilai, yaitu 4 294 967 296 detik. Untuk tanggal Apple, ini kira-kira berusia 136 tahun, jadi Mac yang lebih lama tidak dapat menangani tanggal setelah 2040. Dan jika baterai sistem habis, tanggal disetel ulang ke 0 detik dari awal periode, dan Anda harus menyetel tanggal secara manual setiap kali Anda menyalakan komputer (atau sampai Anda membeli baterai baru).



Namun, keputusan Apple untuk menyimpan tanggal sebagai detik dari permulaan zaman berarti bahwa kami tidak dapat menangani tanggal sebelum permulaan zaman, yang memiliki implikasi luas, seperti yang akan kita lihat. Apple memperkenalkan fitur, bukan bug. Antara lain, ini berarti bahwa sistem operasi Macintosh kebal terhadap "bug milenium" (yang tidak dapat dikatakan tentang banyak aplikasi Mac yang memiliki sistem penanggalan sendiri untuk menghindari pembatasan).



Berpindah. Kami menggunakan Lotus 1-2-3, "aplikasi pembunuh" yang dikembangkan oleh IBM yang membantu meluncurkan revolusi PC, meskipun komputer Apple memiliki VisiCalc, yang membuat komputer pribadi berhasil. Agar adil, jika 1-2-3 tidak muncul, PC tidak akan lepas landas, dan sejarah komputer pribadi dapat berkembang sangat berbeda. Lotus 1-2-3 salah memperlakukan 1900 sebagai tahun kabisat. Ketika Microsoft merilis spreadsheet Multiplan pertamanya, ia memiliki pangsa pasar yang kecil. Dan ketika kami meluncurkan proyek Excel, kami memutuskan tidak hanya untuk menyalin skema penamaan untuk baris dan kolom dari Lotus 1-2-3, tetapi juga untuk memastikan kompatibilitas untuk bug, dengan sengaja memperlakukan 1900 sebagai tahun kabisat. Masalah ini berlanjut hingga hari ini. Artinya, di 1-2-3 itu adalah bug, dan di Excel itu adalah keputusan yang disengaja yang dijaminbahwa semua 1-2-3 pengguna dapat mengimpor spreadsheet mereka ke Excel tanpa mengubah datanya, meskipun mereka salah.



Tapi ada masalah lain. Microsoft pertama kali merilis Excel untuk Macintosh, yang tidak mengenali tanggal sampai 1 Januari 1904. Dan di Excel, permulaan era adalah 1 Januari 1900. Oleh karena itu, developer melakukan perubahan agar programnya mengenali jenis epoch dan menyimpan data di dalamnya sesuai dengan epoch yang diinginkan. Microsoft bahkan menulis artikel penjelasan tentang ini. Dan keputusan ini menyebabkan kesalahan saya.



Sistem ETL saya menerima spreadsheet Excel dari pelanggan yang dibuat di Windows, tetapi juga dapat dibuat di Mac. Oleh karena itu, permulaan era dalam tabel dapat berupa 1 Januari 1900, atau 1 Januari 1904. Bagaimana cara mencari tahu? Format file Excel menunjukkan informasi yang diperlukan, tetapi parser yang saya gunakan tidak menunjukkan (sekarang ditampilkan), dan berasumsi bahwa Anda mengetahui era untuk tabel tertentu. Mungkin, saya bisa menghabiskan lebih banyak waktu untuk memahami biner Excel dan mengirimkan tambalan ke penulis parser, tetapi banyak yang harus saya lakukan untuk klien, jadi saya segera menulis heuristik untuk menentukan zaman. Sederhana saja.



Di Excel, tanggal 5 Juli 1998 dapat ditampilkan dalam format "07-05-98" (sistem Amerika yang tidak berguna), "5 Juli, 98", "5 Juli 1998", "5-Jul-98" atau dalam beberapa format lain yang tidak berguna (ironisnya, salah satu format yang tidak ditawarkan versi Excel saya adalah standar ISO 8601). Namun, di dalam tabel, tanggal yang tidak diformat disimpan sebagai "35981" untuk epoch-1900 atau "34519" untuk epoch-1904 (angka-angka tersebut mewakili jumlah hari sejak awal epoch). Saya hanya menggunakan parser sederhana untuk mengekstrak tahun dari tanggal yang diformat dan kemudian menggunakan pengurai Excel untuk mengekstrak tahun dari tanggal yang tidak diformat. Jika kedua nilai itu berbeda 4 tahun, maka saya mengerti bahwa saya menggunakan sistem dengan era-1904.



Mengapa saya tidak hanya menggunakan tanggal yang diformat? Karena 5 Juli 1998 dapat diformat sebagai "Juli 98" dengan hari dalam sebulan tidak ada. Kami menerima tabel dari begitu banyak perusahaan yang membuatnya dengan cara yang berbeda sehingga kami (dalam hal ini, saya) harus berurusan dengan tanggal. Plus, jika Excel melakukannya dengan benar, kita juga harus melakukannya!



Kemudian saya menemukan 39082. Izinkan saya mengingatkan Anda bahwa Lotus 1-2-3 menganggap 1900 sebagai tahun kabisat, dan ini diulangi dengan tepat di Excel. Dan karena ini menambahkan satu hari ke 1900, banyak fungsi tanggal bisa jadi salah untuk hari itu juga. Artinya, 39082 bisa jadi 1 Januari 2011 (di Mac) atau 31 Desember 2006 (di Windows). Jika "pengurai tahun" saya mengekstraksi tahun 2011 dari nilai yang diformat, maka semuanya baik-baik saja. Namun karena pengurai Excel tidak mengetahui epoch mana yang digunakan, defaultnya adalah epoch-1900, menghasilkan 2006. Aplikasi saya melihat bahwa ada perbedaan 5 tahun, menganggapnya kesalahan, mencatat dan mengembalikan nilai yang tidak diformat.



Untuk menyiasati ini, saya menulis ini (pseudocode):



diff = formatted_year - parsed_year
if 0 == diff
    assume 1900 date system
if 4 == diff
    assume 1904 date system
if 5 == diff and month is December and day is 31
    assume 1904 date system


Dan kemudian semua 40.000 tanggal diuraikan dengan benar.



Di tengah pekerjaan cetak yang besar



Pada awal 1980-an, ayah saya bekerja di Storage Technology, unit bisnis yang sudah tidak beroperasi lagi yang membangun tape drive dan sistem pneumatik untuk tape feeding berkecepatan tinggi.



Mereka mendesain ulang drive sehingga mereka dapat memiliki satu drive pusat "A" yang terhubung ke tujuh drive "B", dan OS kecil dalam RAM yang mengontrol drive "A" dapat mendelegasikan operasi baca dan tulis ke semua drive "B".



Setiap kali drive "A" dimulai, sebuah floppy disk harus dimasukkan ke drive periferal yang terhubung ke "A" untuk memuat sistem operasi ke dalam memorinya. Itu sangat primitif: kekuatan pemrosesan disediakan oleh mikrokontroler 8-bit.



Target audiens untuk peralatan tersebut adalah perusahaan dengan penyimpanan data yang sangat besar - bank, rantai ritel, dll. - yang perlu mencetak banyak label alamat atau laporan mutasi bank.



Satu klien mengalami masalah. Di tengah pekerjaan pencetakan, satu drive "A" tertentu bisa berhenti bekerja, menyebabkan seluruh pekerjaan berhenti bekerja. Agar drive kembali berfungsi, staf harus mem-boot ulang semuanya. Dan jika ini terjadi di tengah-tengah tugas enam jam, maka sejumlah besar waktu komputer yang mahal terbuang percuma dan jadwal seluruh operasi terganggu.



Teknologi Penyimpanan mengirim teknisi. Terlepas dari upaya terbaik mereka, mereka tidak dapat mereproduksi bug dalam kondisi pengujian: tampaknya terjadi di tengah-tengah pekerjaan cetak besar. Masalahnya bukan pada perangkat kerasnya, mereka mengganti semua yang mereka bisa: RAM, mikrokontroler, floppy drive, setiap bagian dari tape drive - masalah tetap ada.



Kemudian teknisi menelepon markas dan memanggil Pakar.



Pemeriksa mengambil kursi dan secangkir kopi, duduk di ruang komputer - pada masa itu ada ruang khusus untuk komputer - dan mengamati staf mengantri pekerjaan cetak besar. Pakar menunggu kegagalan terjadi - dan itu terjadi. Semua orang memandang Pakar - dan dia tidak tahu mengapa ini terjadi. Oleh karena itu, ia memerintahkan tugas untuk antri lagi, dan semua karyawan dengan teknisi kembali bekerja.



Pakar duduk di kursinya lagi dan menunggu kegagalan. Butuh waktu sekitar enam jam dan kegagalan terjadi. Pakar sekali lagi tidak punya ide, kecuali bahwa semua yang terjadi di ruangan yang penuh dengan orang. Dia memerintahkan untuk memulai kembali misi, duduk lagi dan menunggu.



Pada kesalahan ketiga, Pakar melihat sesuatu. Kegagalan terjadi saat personel mengganti sabuk di drive eksternal. Apalagi, kecelakaan itu terjadi begitu salah satu karyawan berjalan melewati ubin tertentu di lantai.



Lantai yang ditinggikan terbuat dari ubin aluminium yang ditempatkan setinggi 6-8 inci. Banyak kabel komputer dipasang di bawah lantai yang ditinggikan sehingga seseorang tidak akan menginjak kabel penting secara tidak sengaja. Ubin dipasang sangat rapat untuk mencegah puing-puing masuk ke bawah lantai.



Ahli tersebut menyadari bahwa salah satu ubin telah berubah bentuk. Ketika seorang karyawan menginjak sudutnya, ubin itu menggesekkan tepinya ke ubin yang berdekatan. Mereka juga menggosok bagian plastik yang menghubungkan ubin, yang menciptakan pelepasan muatan mikro statis yang menciptakan gangguan frekuensi radio.



Saat ini, RAM jauh lebih terlindungi dari gangguan frekuensi radio. Tetapi pada tahun-tahun itu tidak demikian. Ahli tersebut menyadari bahwa interferensi ini mengganggu memori, dan dengannya pengoperasian sistem operasi. Dia menelepon layanan pengawalan, memesan ubin baru, memasangnya sendiri, dan masalahnya hilang.



Ini air pasang!



Ceritanya terjadi di ruang server di lantai empat atau lima sebuah kantor di Portsmouth (menurut saya), di area dermaga.



Suatu hari server Unix dengan database utama crash. Dia di-reboot, tapi dia dengan gembira terus jatuh lagi dan lagi. Kami memutuskan untuk memanggil seseorang dari layanan dukungan.



Dukung kawan ... Kurasa namanya Mark, tapi tidak masalah ... Kurasa aku tidak mengenalnya. Tidak masalah, sungguh. Mari kita tetap di Mark, oke? Luar biasa.



Jadi, beberapa jam kemudian Mark tiba (dari Leeds ke Portsmouth jalurnya tidak dekat, Anda tahu), menyalakan server dan semuanya bekerja tanpa masalah. Dukungan sialan yang khas, pelanggan menjadi sangat kesal karenanya. Mark melihat melalui file log dan tidak menemukan sesuatu yang tidak menyenangkan. Kemudian Mark kembali ke kereta (atau moda transportasi apa pun yang dia gunakan, itu bisa menjadi sapi yang lumpuh sejauh yang saya tahu ... yah, tidak masalah, oke?) Dan kembali ke Leeds, membuang-buang hari.



Server macet lagi malam itu. Ceritanya sama ... server tidak naik. Mark mencoba untuk membantu dari jarak jauh, tetapi klien tidak dapat memulai server.



Kereta lain, bus, lemon meringue, atau omong kosong lainnya, dan Mark kembali ke Portsmouth. Lihat, server melakukan booting tanpa masalah! Keajaiban. Tandai memeriksa selama beberapa jam bahwa semuanya beres dengan sistem operasi atau perangkat lunak, dan pergi ke Leeds.



Sekitar tengah hari, server macet (tenang saja!). Kali ini, tampaknya bijaksana untuk mendatangkan orang-orang pendukung perangkat keras untuk menggantikan server. Tapi tidak, setelah sekitar 10 jam itu juga jatuh.



Situasi itu berulang selama beberapa hari. Server aktif, mogok setelah sekitar 10 jam dan tidak mulai selama 2 jam berikutnya. Mereka memeriksa pendinginan, kebocoran memori, mereka memeriksa semuanya, tetapi mereka tidak menemukan apa pun. Kemudian tabrakan berhenti.



Minggu berlalu tanpa beban ... semua orang senang. Senang sampai semuanya dimulai lagi. Gambarannya sama. 10 jam kerja, 2-3 jam waktu henti ...



Dan kemudian seseorang (saya pikir mereka mengatakan kepada saya bahwa orang ini tidak ada hubungannya dengan IT) berkata:



"Inilah air pasang!"



Seruan itu disambut dengan tatapan kosong, dan, mungkin, tangan seseorang gemetar pada tombol untuk memanggil penjaga.



"Dia berhenti bekerja dengan arus."



Ini akan tampak seperti konsep yang sama sekali asing bagi staf dukungan TI yang hampir tidak membaca Tide Yearbook sambil duduk minum kopi. Mereka menjelaskan bahwa itu tidak ada hubungannya dengan arus pasang karena server telah berjalan selama seminggu tanpa hambatan.



"Gelombangnya rendah minggu lalu dan tinggi minggu ini."



Sedikit istilah bagi mereka yang tidak memiliki izin untuk mengoperasikan kapal pesiar. Pasang surut tergantung pada siklus bulan. Dan saat Bumi berputar, setiap 12,5 jam tarikan gravitasi Matahari dan Bulan menciptakan gelombang pasang. Pada awal siklus 12,5 jam terjadi air pasang, di tengah siklus terjadi pasang surut, dan di akhir siklus terjadi pasang kembali. Tapi saat orbit bulan berubah, begitu pula perbedaan antara pasang surut dan arus. Ketika Bulan berada di antara Matahari dan Bumi atau di sisi berlawanan dari Bumi (bulan purnama atau tanpa bulan), kita mendapatkan pasang Syzygy - pasang tertinggi dan pasang surut terendah. Pada setengah bulan kita mendapatkan pasang kuadratur - pasang terendah. Perbedaan antara kedua ekstrim tersebut sangat berkurang. Siklus bulan berlangsung selama 28 hari: syzygy - quadrature - syzygy - quadrature.



Ketika kekuatan pasang surut dijelaskan kepada teknisi, mereka langsung berpikir untuk memanggil polisi. Dan itu cukup logis. Tapi ternyata pria itu benar. Dua minggu sebelumnya, sebuah kapal perusak telah berlabuh di dekat kantor. Setiap kali air pasang menaikkannya ke ketinggian tertentu, pos radar kapal akan berada di lantai ruang server. Dan radar (atau peralatan perang elektronik, atau mainan militer lainnya) menciptakan kekacauan di komputer.



Misi penerbangan untuk roket



Saya diperintahkan untuk memasang sistem kendali dan pemantauan peluncuran rudal yang besar (sekitar 400 ribu baris) untuk versi baru dari sistem operasi, kompilator, dan bahasa. Lebih tepatnya, dari Solaris 2.5.1 pada Solaris 7, dan dari Verdix Ada Development System (VADS) yang ditulis dalam Ada 83 menjadi sistem Rational Apex Ada yang ditulis dalam Ada 95. VADS dibeli oleh Rational dan produknya sudah usang, meskipun Rational mencoba menerapkan versi yang kompatibel dari paket khusus VADS untuk memudahkan transisi ke kompiler Apex.



Tiga orang membantu saya hanya untuk mendapatkan kode yang dikompilasi dengan rapi. Butuh waktu dua minggu. Dan kemudian saya bekerja sendiri untuk membuat sistem bekerja. Singkatnya, itu adalah arsitektur dan implementasi terburuk dari sistem perangkat lunak yang pernah saya temui, jadi butuh dua bulan lagi untuk menyelesaikan porting. Kemudian sistem tersebut diserahkan untuk pengujian, yang memakan waktu beberapa bulan lagi. Saya segera memperbaiki bug yang saya temukan selama pengujian, tetapi jumlahnya dengan cepat berkurang (kode sumbernya adalah sistem produksi, jadi fungsinya bekerja dengan cukup andal, saya hanya harus menghapus bug yang muncul saat beradaptasi dengan kompiler baru). Pada akhirnya, ketika semuanya berjalan sebagaimana mestinya, saya dipindahkan ke proyek lain.



Dan pada hari Jumat sebelum Thanksgiving, telepon berdering.



Sekitar tiga minggu kemudian, peluncuran roket akan diuji, dan dalam tes laboratorium penghitungan mundur, urutan perintah diblokir. Dalam kehidupan nyata, ini akan menyebabkan gangguan pada pengujian, dan jika penyumbatan terjadi dalam beberapa detik setelah menghidupkan mesin, maka beberapa tindakan yang tidak dapat diubah akan terjadi dalam sistem tambahan, yang akan memakan waktu lama - dan mahal - untuk menyiapkan ulang roket. Ini tidak akan dimulai, tetapi banyak orang akan sangat kesal karena kehilangan waktu dan uang yang sangat, sangat besar. Jangan biarkan siapa pun memberi tahu Anda bahwa Departemen Pertahanan membelanjakan uang begitu saja - saya belum bertemu dengan manajer kontrak yang tidak memiliki anggaran pertama atau kedua, diikuti oleh jadwal.



Pada bulan-bulan sebelumnya, uji hitung mundur ini telah dijalankan ratusan kali dalam berbagai variasi, dengan hanya beberapa hambatan kecil. Jadi kemungkinan terjadinya hal ini sangat rendah, tetapi konsekuensinya sangat signifikan. Lipat gandakan kedua faktor ini, dan Anda akan memahami bahwa berita tersebut meramalkan minggu libur yang hancur bagi saya dan lusinan teknisi dan manajer.



Dan perhatian ditarik kepada saya sebagai orang yang mem-porting sistem.



Seperti kebanyakan sistem keamanan kritis, banyak parameter dicatat di sini, jadi cukup mudah untuk mengidentifikasi beberapa baris kode yang dijalankan sebelum sistem rusak. Dan tentu saja, sama sekali tidak ada yang luar biasa tentang mereka, ekspresi yang sama berhasil dilakukan ribuan kali secara harfiah selama proses yang sama.



Kami memanggil orang-orang dari Apex ke Rational karena mereka telah mengembangkan kompiler dan beberapa rutinitas yang mereka kembangkan dipanggil dalam kode yang mencurigakan. Mereka (dan semua orang) terkesan dengan kebutuhan untuk mencari tahu penyebab masalah signifikansi nasional literal.



Karena tidak ada yang menarik di log, kami memutuskan untuk mencoba mereproduksi masalah di laboratorium lokal. Ini bukanlah tugas yang mudah, karena peristiwa tersebut terjadi kira-kira sekali setiap 1000 kali berjalan. Salah satu alasan yang seharusnya adalah bahwa panggilan ke fungsi mutex yang dikembangkan vendor (bagian dari kumpulan migrasi VADS)Unlocktidak mengarah ke pembukaan kunci. Utas panggilan memproses pesan detak jantung, yang biasanya tiba setiap detik. Kami menaikkan frekuensi menjadi 10 Hz, yaitu 10 kali per detik, dan mulai berjalan. Setelah sekitar satu jam, sistem terkunci. Di log, kami melihat bahwa urutan pesan yang direkam sama seperti saat pengujian gagal. Kami melakukan beberapa kali lari lagi, sistem diblokir secara stabil 45-90 menit setelah start, dan setiap log berisi trek yang sama. Terlepas dari kenyataan bahwa kami secara teknis menjalankan kode yang berbeda sekarang - kecepatan pesan berbeda - perilaku sistem diulang, jadi kami memastikan bahwa skenario pemuatan ini mengarah ke masalah yang sama.



Sekarang perlu untuk mencari tahu persis di mana urutan ekspresi kunci itu terjadi.



Implementasi ini menggunakan sistem tugas Ada dan sangat buruk digunakan. Tasks adalah konstruksi tingkat tinggi yang dapat dieksekusi secara bersamaan di Ada, semacam rangkaian eksekusi, yang baru saja dibangun ke dalam bahasa itu sendiri. Ketika dua tugas perlu berinteraksi, mereka "bertemu", bertukar data yang diperlukan, dan kemudian menghentikan pertemuan tersebut dan kembali ke kinerja independen mereka. Namun, sistem tersebut diterapkan secara berbeda. Setelah target bertemu, target itu akan bertemu dengan target lain, yang kemudian akan bertemu dengan target ketiga, dan seterusnya, sampai beberapa proses selesai. Setelah itu, semua pertemuan ini berakhir dan setiap tugas harus kembali dieksekusi. Artinya, kami berurusan dengan sistem panggilan fungsi termahal di dunia,yang menghentikan seluruh proses "multitasking" saat memproses beberapa data masukan. Dan sebelumnya, hal ini tidak menimbulkan masalah hanya karena throughput yang sangat rendah.



Saya menjelaskan mekanisme tugas ini karena ketika pertemuan diminta atau diharapkan selesai, "sakelar tugas" dapat terjadi. Artinya, prosesor dapat mulai memproses tugas lain yang siap dijalankan. Ternyata ketika satu tugas siap untuk bertemu dengan tugas lain, pelaksanaan tugas yang sama sekali berbeda dapat dimulai, dan akhirnya kontrol kembali ke pertemuan pertama. Dan peristiwa lain dapat terjadi yang mengarah ke pengalihan tugas; salah satu peristiwa tersebut adalah pemanggilan fungsi sistem, seperti mencetak atau menjalankan mutex.



Untuk memahami baris kode mana yang menyebabkan masalah, saya perlu menemukan cara untuk merekam kemajuan urutan ekspresi tanpa memicu sakelar tugas, yang dapat mencegah terjadinya crash. Jadi saya tidak bisa memanfaatkanPut_Line()untuk tidak melakukan operasi I / O. Anda dapat mengatur variabel penghitung atau sesuatu seperti itu, tetapi bagaimana saya dapat melihat nilainya jika saya tidak dapat menampilkannya di layar?



Selain itu, saat memeriksa log, ternyata, meskipun pemrosesan pesan detak jantung membeku, yang memblokir semua operasi I / O dari proses tersebut dan tidak mengizinkan pemrosesan lain dilakukan, tugas independen lainnya terus dijalankan. Artinya, pekerjaan itu tidak diblokir seluruhnya, hanya rantai tugas (kritis).



Ini adalah pengait yang diperlukan untuk mengevaluasi ekspresi pemblokiran.



Saya membuat paket Ada yang berisi tugas, tipe enumerasi, dan variabel global tipe itu. Literal disebutkan diikat ke ekspresi tertentu urutan bermasalah (misalnya Incrementing_Buffer_Index, Locking_Mutex,Mutex_Unlocked), lalu menyisipkan ekspresi tugas ke dalamnya, yang menetapkan pencacahan terkait ke variabel global. Karena kode objek dari semua ini tetap konstan dalam memori, pengalihan tugas sebagai hasil dari pelaksanaannya sangat tidak mungkin. Pertama-tama, kami mencurigai ekspresi yang dapat mengalihkan tugas, karena pemblokiran terjadi selama eksekusi, dan tidak ditampilkan saat mengalihkan tugas kembali (karena beberapa alasan).



Tugas pelacakan hanya berjalan dalam satu putaran dan secara berkala memeriksa untuk melihat apakah nilai variabel global telah berubah. Dengan setiap perubahan, nilainya disimpan ke file. Kemudian tunggu sebentar dan cek baru. Saya menulis variabel ke file karena tugas dijalankan hanya ketika sistem memilihnya untuk dieksekusi saat mengalihkan tugas di area masalah. Apa pun yang terjadi dalam tugas ini tidak akan memengaruhi tugas terkunci yang tidak terkait lainnya.



Diharapkan saat sistem mencapai eksekusi kode yang bermasalah, variabel global akan disetel ulang dengan setiap ekspresi berikutnya. Kemudian sesuatu akan terjadi, yang mengarah ke pengalihan tugas, dan karena frekuensi eksekusinya (10 Hz) lebih rendah daripada tugas pemantauan, monitor dapat memperbaiki nilai variabel global dan menuliskannya. Dalam situasi normal, saya bisa mendapatkan urutan berulang dari subset pencacahan: nilai terakhir variabel pada saat peralihan tugas. Saat digantung, variabel global tidak boleh berubah lagi, dan nilai terakhir yang ditulis akan menunjukkan ekspresi mana yang tidak menyelesaikan eksekusi.



Meluncurkan kode pelacakan. Itu membeku. Dan pemantauannya bekerja seperti jarum jam.



Log berakhir dengan urutan yang diharapkan, yang diinterupsi oleh nilai yang menunjukkan bahwa mutex dipanggil Unlockdan tugas ditunda - seperti yang terjadi dengan ribuan panggilan sebelumnya.



Insinyur puncak saat ini dengan panik menganalisis kode mereka dan menemukan tempat di mutex di mana, secara teori, kunci dapat terjadi. Tetapi kemungkinannya sangat kecil, karena hanya rangkaian peristiwa tertentu yang terjadi pada waktu tertentu yang dapat menyebabkan pemblokiran. Anak laki-laki hukum Murphy, itu hukum Murphy.



Untuk melindungi bagian kode ini, saya mengganti panggilan ke fungsi mutex (dibangun di atas fungsi mutex OS) dengan paket Ada mutex asli kecil untuk mengontrol akses mutex ke bagian ini.



Menempelkannya ke dalam kode dan menjalankan pengujian. Tujuh jam kemudian, kode itu terus berfungsi.



Kode saya diserahkan ke Rasional, di mana ia dikompilasi, dibongkar dan diverifikasi bahwa ia tidak menggunakan pendekatan yang sama yang digunakan dalam fungsi mutex yang bermasalah.



Itu adalah tinjauan kode yang paling ramai dalam karir saya :) Ada sekitar sepuluh insinyur dan manajer di ruangan bersama saya, selusin lebih orang terhubung melalui panggilan konferensi - dan mereka semua memeriksa sekitar 20 baris kode.



Kode telah ditinjau, file baru yang dapat dieksekusi dibangun dan dikirimkan untuk pengujian regresi formal. Beberapa minggu kemudian, tes hitung mundur berhasil dan roket lepas landas.



Oke, ini semua bagus dan indah, tapi apa gunanya cerita ini?



Itu adalah masalah yang sangat menjijikkan. Ratusan ribu baris kode, eksekusi paralel, lebih dari selusin proses yang berinteraksi, arsitektur yang buruk dan implementasi yang buruk, antarmuka untuk sistem tertanam, dan jutaan dolar yang dihabiskan. Tidak ada tekanan, benar.



Saya bukan satu-satunya yang menangani masalah ini, meskipun saya menjadi sorotan saat melakukan porting. Tetapi meskipun saya melakukannya, ini tidak berarti bahwa saya memahami ratusan ribu baris kode, atau setidaknya membacanya. Kode dan log dianalisis oleh para insinyur di seluruh negeri, tetapi ketika mereka memberi tahu saya hipotesis mereka tentang penyebab kegagalan, saya butuh waktu setengah menit untuk membantahnya. Dan ketika saya diminta untuk menganalisis teori, saya menyampaikannya kepada orang lain, karena jelas bagi saya bahwa para insinyur ini salah jalan. Terdengar lancang? Ya, benar, tetapi saya menolak hipotesis dan permintaan karena alasan yang berbeda.



Saya memahami sifat masalahnya. Saya tidak tahu persis di mana atau mengapa, tetapi saya tahu persis apa yang terjadi.



Selama bertahun-tahun, saya telah mengumpulkan banyak pengetahuan dan pengalaman. Saya adalah salah satu pelopor penggunaan Ada, saya mengerti kelebihan dan kekurangannya. Saya tahu bagaimana pustaka runtime Ada menangani tugas dan menangani eksekusi paralel. Dan saya pandai pemrograman tingkat rendah pada tingkat memori, register dan assembler. Dengan kata lain, saya memiliki pengetahuan yang mendalam di bidang saya. Dan saya menggunakannya untuk menemukan penyebab masalahnya. Saya tidak hanya mengatasi bug, tetapi juga menemukan cara menemukannya di lingkungan eksekusi yang sangat sensitif.



Kisah-kisah perjuangan dengan kode semacam itu tidak terlalu menarik bagi mereka yang tidak akrab dengan keanehan dan kondisi perjuangan semacam itu. Tetapi cerita-cerita ini membantu untuk memahami apa yang diperlukan untuk memecahkan masalah yang sangat sulit.



Anda harus lebih dari sekadar seorang programmer untuk memecahkan masalah yang sangat sulit. Anda perlu memahami “takdir” kode, bagaimana kode berinteraksi dengan lingkungannya, dan cara kerja lingkungan itu sendiri.



Dan kemudian Anda memiliki minggu liburan yang manja.






Bersambung.



All Articles