Błędy systemowe są zgłaszane, gdy wywołanie systemu operacyjnego zwraca kod błędu...
Serwis znalezionych hasełOdnośniki
- Smutek to uczucie, jak gdyby się tonęło, jak gdyby grzebano cię w ziemi.
- zobowi za wobec pracowników (gdy wynagrodzenia s płacone „z dołu”), zobowi za wobec dostawców, wynikaj cych z operacyjnego (manipulacyjnego) odroczenia...
- Kiedy Canan przejął zarządzanie codziennymi operacjami magazynu, Lovejoy jeszcze bardziej skupił swą uwagą na rekrutacji, sprowadzając ostatecznie jeszcze...
- Mimo to w żyłach elfa płynęła adrenalina wywołana łowami – górskim szlakiem poniżej uciekał tuzin orków – a jeszcze bardziej...
- ZWRACAJ UWAGĘ NA SWOJE MEMORANDAInformacje wewnętrzne firmy (memoranda) to kolejna pułapka...
- Podczas tych narzekań, które były zapewne wynikiem rozczarowania i osobistej urazy, wywołanej faktem, że jej stary pracodawca wolał inną, Artur Gride...
- Operacje wejścia-wyjścia Zmienne typu int, double i char są zmiennymi arytmetycznymi, przystosowanymi odpowiednio do przechowywania...
- Ponisza lista uzasadnie i sprzeciww co do etycznych aspektw pracy operacyjnej odzwierciedla przebieg dyskusji na ten temat...
- Patrycja jednak falowała zupełnie osobno w sennym, odurzającym rytmie, prawie nie zwracając uwagi na charczenie głośników...
- Ocena ryzyka: WysokieTo jedna z najbardziej newralgicznych operacji omawianego przypadku użycia...
- adne z nich nie zwracao najmniejszej nawet uwagi ani na ludzi obecnych na mostku, ani na zbliajcych si na ekranie...
Smutek to uczucie, jak gdyby się tonęło, jak gdyby grzebano cię w ziemi.
W systemach POSIX te błędy mają nazwy podobne do EAGAIN czy EPERM. W systemach uniksowych możemy uzyskać listę tych błę-
dów poleceniem man errno.
Ruby opakowuje każdy z tych błędów w oddzielny obiekt wyjątku. Każdy z nich jest podklasą SystemCallError i każdy jest zdefiniowany w module nazwanym Errno. Oznacza to, że spotkamy się z wyjątkami o nazwach klasy typu Errno::EAGAIN, Errno::EIO czy Errno::EPERM. Jeśli chcemy uzyskać oryginalny kod błędu, pamiętajmy, że obiekty wyjątków Errno posiadają specjalną stałą klasy nazwaną (jakże niespodziewanie) Errno, która prze-chowuje tą wartość.
Errno::EAGAIN::Errno → 35
Errno::EPERM::Errno → 1
Errno::EIO::Errno → 5
Errno::EWOULDBLOCK::Errno → 35
Zwróćmy uwagę, że EWOULDBLOCK i EAGAIN mają ten sam numer błędu. To cecha systemu operacyjnego komputera, którego użyliśmy do tworzenia tej książki — obie stałe odpowiadają temu samemu kodowi błędu. Aby sobie z tym poradzić, Ruby tak wszystko aranżuje, aby Errno::EAGAIN i Errno:: 1 To porównanie jest możliwe, ponieważ wyjątki są klasami, a klasy z kolei są rodzajem modułu. Metoda === dla modułów zwraca true, jeśli klasa operandu jest taka sama lub należy do przodków odbiorcy.
158
Część I • Płaszczyzny Ruby
EWOULDBLOCK były traktowane tak samo przez klauzulę rescue. Jest to realizo-wane poprzez przedefiniowanie SystemCallError#=== w taki sposób, że po-równanie dwóch podklas SystemCallError powoduje porównywanie ich kodów błędu, a nie ich pozycji w hierarchii.
Sprzątanie
Czasem musimy zagwarantować, że dane przetwarzanie jest dokonywane na końcu bloku kodu, niezależnie od tego, czy zgłaszany jest wyjątek. Na przykład możemy otworzyć plik przy wejściu do bloku i musimy się upew-nić, że zostanie on zamknięty wraz z zakończeniem bloku.
Służy temu klauzula ensure, która znajduje się za ostatnią klauzulą rescue i zawiera kawałek kodu, który będzie zawsze wykonany wraz z zakończeniem bloku. Nie ma znaczenia, czy blok kończy pracę normalnie czy został
przerwany przez nieprzechwycony wyjątek — blok ensure będzie zawsze wykonany.
f = File.open("testfile")
begin
# .. przetwarzanie
rescue
# .. obsługa błędu
ensure
f.close unless f.nil?
end
Klauzula else jest podobną, ale mniej użyteczną konstrukcją. Jeśli jest obecna, występuje po klauzuli rescue, ale przed ensure. Ciało klauzuli else jest wykonywane jedynie wówczas, gdy żadne wyjątki nie są zgłaszane w głównym ciele kodu.
f = File.open("testfile")
begin
# .. przetwarzanie
rescue
# .. obsługa błędu
else
puts "Gratulacje -- nie ma błędów!"
ensure
f.close unless f.nil?
end
Rozdział 8. • Zgłaszanie i przechwytywanie wyjątków 159
Zagraj to jeszcze raz
Czasem możemy być w stanie naprawić przyczynę wyjątku. W takich przy-padkach używamy instrukcji retry w klauzuli rescue do ponownego wywo-
łania całego bloku begin-end. Może to prowadzić do powstania pętli nie-skończonych, dlatego należy zachować ostrożność (i na wszelki wypadek trzymać palce na klawiszach przerywających pracę programu).
Jako przykład kodu, który ponownie wywołuje kod po wystąpieniu wyjąt-ków, przedstawimy nieco zmieniony fragment biblioteki net/smtp.rb autor-stwa Minero Aoki.
@esmtp = true
begin
# Najpierw spróbuj zalogować się rozszerzonym loginem. Jeśli to się nie powiedzie,
# ponieważ serwer go nie obsługuje, spróbuj standardowego sposobu logowania.
if @esmtp then
@command.ehlo(helodom)
else
@command.helo(helodom)
end
rescue ProtocolError
if @esmtp then
@esmtp = false
retry
else
raise
end
end
Kod najpierw próbuje połączyć się z serwerem SMTP za pomocą pole-cenia EHLO, które nie jest zawsze obsługiwane. Jeśli próba połączenia za-kończy się niepowodzeniem, kod ustawia wartość zmiennej @esmtp na false i próbuje ponownie nawiązać połączenie. Jeśli ponownie wystąpi błąd, do jednostki wywołującej zgłaszany jest wyjątek.
Zgłaszanie wyjątków
Jak do tej pory byliśmy w obronie i obsługiwaliśmy wyjątki zgłaszane przez innych. Czas odwrócić sytuację i przejść do natarcia. Niektórzy mówią, że autorzy tej niniejszej publikacji zawsze są w natarciu, ale to już temat na inną książkę.
160
Część I • Płaszczyzny Ruby