Wprowadzenie
Nieformalny opis
Przegląd Komponent wykonawczy Zdalnego Agenta został zaprojektowany, aby wspierać bezpieczne wykonanie, kontrolowanych programowo, zadań na pokładzie statku kosmicznego. Kiedy zadanie jest (oczywiście dynamicznie) uruchamiane, jeszcze przed przejściem do swojej głównej funkcji, próbuje najpierw osiągnąć wymagane własności. Jednak właściwości mogą się zmienić w czasie działania, a wtedy zadanie, które od takich zmienionych właściwości zależy musi zostać przerwane. Aby uprościć zaprogramowanie pojedynczego zadania, Zdalny Agent modeluje urządzenia znajdujące się na pokładzie w kategoriach różnych właściwości jakie mogą one posiadać i przechowuje te informacje w bazie danych. Komponent wykonawczy zapewnia zarówno mechanizm dla osiągania jaki i zachowywania właściwości, używając blokad w celu zapobiegnięcia równoległego uruchomienia zadania z niezgodnymi wartościami właściwości. Kontrolę nad tym ma demon, który kontroluje bazę danych reprezentującą stan statku kosmicznego. Jeśli istnieje niezgodność między danymi znajdującymi się w bazie danych a tablicą blokad właściwości, demon zawiesza wszystkie zadania przypisane do właściwości i stara się przywrócić jej pożądany stan. Demon zwykle działa w tle, a uaktywnia się dopiero w momencie gdy zachodzi jakieś zdarzenie zmieniające stan bazy danych lub tablicę blokad.
Komponent
wykonawczy zezwala przypisanie konkretnej właściwości wielu metod jej
osiągnięcia. W momencie zainicjowania takiej metody, wykonawca woła
odpowiednia dla stanu metodę, która coś konkretnego robi (jednak ta
właściwość nie będzie przedmiotem weryfikacji i dlatego przyjęte
zostanie, iż zadanie może osiągnąć właściwość bezpośrednio). Typy danych Właściwości – określają stan statku kosmicznego (nazwa właściwości, wartość właściwości). Baza danych – przechowuje aktualizowane na bieżąco informacje o stanie statku (jego właściwościach). Tabela blokad właściwości – przechowuje trójki {właściwość, subskrybenci, osiągnięta} (działanie podczas niezgodności z BD opisane powyżej). Subskrybenci są przechowywani ponieważ właściwość o konkretnej własności może spełniać warunki dal wielu zadań. Zdarzenia – w momencie zmiany tablicy blokad właściwości lub bazy danych demon monitorujący zostaje o tym poinformowany, aby mógł sprawdzić odświeżony stan systemu. W tym celu wprowadzone zostały listy zdarzeń: zmiany tabeli blokad (Snarf_Event) oraz zmiany bazy danych (Memory_Event). Jakikolwiek proces (zadanie lub demon), który chce czekać na konkretne zdarzenie (zmieniające właściwość) wywołuje procedurę czekania (wait) – zamieszczającą proces w kolejce oczekujących. Kiedy następuje zmiana właściwości w bazie danych wszystkie procesy będące na liście oczekujących zostają o tym poinformowane i restartowane. Procesy Zadania – przed wykonaniem starają się osiągnąć pożądane wartości właściwości, najpierw je blokując w tabeli blokad (snarfing). Może to nastąpić jedynie gdy jest zgodne z pozostałymi blokadami (nie ma konfliktu dostępu) wpp. zadanie zostaje porzucone. Tworzący blokadę jest jej właścicielem i jest odpowiedzialny za osiągnięcie właściwości – zmianę jej wartości w bazie danych (udane zmienia wartość parametru achived na true, wpp. zadanie zostaje porzucone). Pozostałe zadania wpisane na listę subskrybentów czekają na zmiennej Memory_Event. Przed zakończeniem zadanie jest zobowiązane do sprawdzenia czy nie jest ostatnim blokującym właściwości i ewentualnie ma zdjąć z niej blokadę. Demon – gwarantuje zachowanie osiągniętej właściwości w czasie wykonania zadania (zgodność wartości w tabeli blokad i bazie danych). Normalnie demon „śpi” czekając na zdarzenie modyfikujące bazę danych lub tablicę blokad. Kiedy się „budzi” sprawdza wszystkie blokady i dla każdej z polem achived = true sprawdza czy dana właściwość jest w bazie danych. Jeśli jej nie ma wszystkie zadania do niej się odwołujące są zawieszane i zainicjalizowana zostaje procedura mająca przywrócić oczekiwane wartości. Po zbadaniu wszystkich blokad demon „usypia” czekając na kolejne zdarzenie. Formalne przekształcenie do PROMELI
Analiza wybranych właściwościi Właściwości do sprawdzenia
Sprawdzenie powyższych właściwości za pomocą formuł LTL doprowadziło do odnalezienia 4 poważnych błędów oraz jednego problemu z wydajnością.
Kiedy zadanie kończy działanie, oczekujemy, że nie jest już subskrybentem żadnej wartości właściwości. Przebieg W tym momencie w środowisku występuje niezgodność w bazie danych, powodująca zmianę wartości właściwości używanej przez zadanie. Demon ją wykrywa i przerywa działanie zadania zmieniając jego stan na ABORTED. W wyniku powyższego przebiegu nie zostają zdjęte blokady używane przez zadanie. Jest to spowodowane brakiem ochrony, dla zadania, w trakcie próby wykonania procedury release_locks. Rozwiązanie - dodanie ochrony zwalniania blokad, w taki sposób, żeby nie było możliwe przerwanie. Programiści ocenili
możliwość wystąpienia tego błędu w czasie lotu dość wysoko. Dodatkowo
potwierdzili, że najprawdopodobniej nie zostałby on odkryty w żaden inny
sposób (ponieważ występuje jedynie w wielowątkowym środowisku i bardzo
specyficznych okolicznościach). Błąd 2 - Własność przerwania Jeśli po zmianie wartości właściwości w BD przez zadanie nastąpi zmiana w środowisku to zadanie zostanie zakończone lub przerwane. Przebieg W tym momencie środowisko zmienia jedną ze zmiennych i sygnalizuje MEMORY_EVENT. Jednak sygnał ten nie spowoduje niczego, ponieważ demon jeszcze nie wywołał wait_for_events. Następnie demon nie orientując sie o żadnej zmianie wywołuje wait_for_events. Rozwiązanie - obwarowanie wewnętrznych działań demona sekcją krytyczną (atomic) Programiści przyznali
się do klasycznego błędu - nie opakowali procedur sekcją krytyczną,
podziękowali za wytknięcie im tego błędu i stwierdzili jednocześnie, że
wcześniej lub później zostałby odkryty ponieważ takich błędów w kodzie
popełnili mnóstwo. Błąd 3 - Własność przerwania Ponownie sprawdzamy powyższą własność na poprawionym modelu. Przebieg Przez cały czas zadanie działa i nie zostaje przerwane. Rozwiązanie - w momencie zauważenia tego przebiegu nie został on zakwalifikowany jako błędny (a raczej jako błąd w tłumaczeniu Lisp'a na PROMELE), jednak nawet później nigdy nie udało się go poprawić. Według programistów jest to znany im błąd modelu (który już był na liście "rzeczy do zrobienia"), powodujący przedłużenie czasu między wystąpieniem niezgodności a poinformowaniem o tym zadania. Jednak weryfikujący dodatkowo zauważyli, że może się zdarzyć iż zadanie może nigdy nie zostać poinformowane... (jednak ten błąd specjalnie nie przejął programistów) Błąd 4 - Własność przerwania Poprawiono kod, tak aby nie dochodziło do sytuacji z błędu 3 (zezwolono na jego występowanie). Z takim kodem zapytanie zmieniono na "we wszystkich stanach, jeśli wartość właściwości zostanie nieoczekiwanie zmieniona, to zadanie w końcu zostanie, bądź zakończone, bądź właściwość zostanie naprawiona". Przebieg W momencie wystąpienia niezgodności, nie zostaje ona odkryta przez demona i zadanie nie zostaje przerwane. Rozwiązanie - obwarowanie sekcją krytyczną operacji w achieve_locks_property. Drugi z błędów ocenionych przez programistów jako niewykrywalny przez inne metody. Błąd 5 - Problem wydajnościowy W czasie analizowania przebiegów został odkryty piąty błąd występujący w kodzie Lisp'a. W PROMELI dotyczy on kodu procesu demona. Polega ona na tym, że sprawdzanie blokad następuje dwukrotnie po tym jak demon zasypia i zostaje obudzony przez sygnał. Licznik nadejścia sygnałów od zdarzeń zostaje dwa razy powiększony. Programiści potwierdzili istnienie tego błędu jednak nadali mu niski priorytet (bo to tylko kwestia wydajności ;) ). |
|||
Piotr Góra, maj 2004