Statische Codeanalyse

Bugs und Defekte in Multitasking-Software eliminieren

22.01.2009 | Autor / Redakteur: David Kalinsky* / Martina Hafner

*Dr, David Kalinsky ist Leiter für Kundentrainings bei D. Kalinsky Associates Technical Training, USA und ein beliebter Dozent in USA, Europa und Israel. Kontakt: david@kalinskyassociates.com.
*Dr, David Kalinsky ist Leiter für Kundentrainings bei D. Kalinsky Associates Technical Training, USA und ein beliebter Dozent in USA, Europa und Israel. Kontakt: david@kalinskyassociates.com.

Fehler in RTOS-basierendem Code

Bild 2: eine Race Condition im Temperaturdaten-Bereich verursacht Anzeigefehler
Bild 2: eine Race Condition im Temperaturdaten-Bereich verursacht Anzeigefehler

Seit einigen Monaten werden statische Analysetools vermehrt auch in RTOS-Taskingmodellen eingesetzt. Sie eignen sich damit auch für das Auffinden von Multitaskingfehlern, die beim Einsatz eines RTOS oft auftreten können, wie z.B Race Conditions, Task Blocking, Deadlocks, Lockouts. Eine Race Condition ist eine Wettbewerbssituation, die auftritt, wenn Tasks ohne Locking-Mechanismus auf gemeinsame Daten zugreifen, wie in Abbildung 2 dargestellt.

Die Task “Anzeige” muss hier ausgeführt werden und greift auf den gemeinsamen Datenbereich zu, der gerade von der Task „Messung“ beschrieben wird. Beim Ausführen der Software kann dies sporadische Datenkorruptionen verursachen. Es kommt zu einer sogenannten Race Condition, hier dargestellt als Anzeigefehler: In einer Abfolge von Anzeigewerten von 100 und 99 erscheint ein Wert von 199. Ein statisches Analysetool überprüft in diesem Fall den Sourcecode auf Daten, auf die mehrere Tasks zugegriffen haben, von denen mindestens eine ein Schreibvorgang war. Das Tool prüft, dass das Lesen und Schreiben nicht als atomare Operationen stattfindet. Dann wird der Code für alle diese Datenbereiche nochmals durchsucht, um herauszufinden, welches Software-Lock vor dem Zugriff auf diese Daten normalerweise gesperrt und nach dem Zugriff wieder freigegeben wird. Das Lock bezeichnet man in diesem Fall als „Bewacher“ der Daten. Anschließend wird der Code nochmals durchsucht, um herauszufinden, wo Zugriffe auf diese Daten möglich sind, d.h. wo der „Bewacher“ die Daten nicht ausreichend schützt. Fehler dieser Art werden als Softwaredefekt angezeigt.

Bild 3: Beispiel für Task-Blocking. Eine Task hält über einen langen Zeitraum ein Lock, wodurch eine Task höherer Priorität sehr lange blockiert wird.
Bild 3: Beispiel für Task-Blocking. Eine Task hält über einen langen Zeitraum ein Lock, wodurch eine Task höherer Priorität sehr lange blockiert wird.

Ein weiterer Gleichzeitigkeitsfehler, den viele statische Analysetools beheben können, ist das Task Blocking: Eine Task hält über einen langen Zeitraum ein Lock, wodurch eine Task höherer Priorität sehr lange blockiert wird. Es handelt sich dabei um eine Variante der Prioritätsinversion. Abbildung 3 zeigt ein Beispiel mit POSIX.

Andere Tasks (POSIX ‘Threads’) höherer Priorität, die den Mutex sperren wollen, könnten in diesem Beispiel bis zu drei Sekunden blockiert werden. Dies ist natürlich eine verhältnismäßig einfache Form der Prioritätsinversion und weit entfernt von der automatischen Identifizierung einer „unbegrenzten Prioritätsinversion“ - ein viel subtileres Phänomen, doch ein gravierender Softwaredesignfehler.

Bild 4: beispielhaftes Task-Deadlock
Bild 4: beispielhaftes Task-Deadlock

Mit statischer Analyse lassen sich auch verschiedene Arten von Task-Deadlocks erkennen; beispielhaft in Abb. 4 dargestellt.Wenn die Software tatsächlich ausgeführt wird, tritt die Verklemmungssituation vielleicht nur selten auf, doch ein statisches Analysetool erkennt bei jeder Analyse das Deadlock-Potential. Das Tool sucht erst nach einer zirkulären Abhängigkeit zwischen Tasks und anschließend nach einer inkonsistenten Reihenfolge von gemeinsamen Locks, welche die Tasks miteinander verbinden.

Bild 5: Beispiel für einen Lockout-Fehler. Wenn diese Task vergisst, ihr Lock wieder freizugeben, müssen andere Tasks für unbestimmte Zeit darauf warten.
Bild 5: Beispiel für einen Lockout-Fehler. Wenn diese Task vergisst, ihr Lock wieder freizugeben, müssen andere Tasks für unbestimmte Zeit darauf warten.

Auch eine vierte Klasse von Gleichzeitigkeitsfehlern lässt sich mit statischer Analyse auffinden, die sogenannten Lockouts. Abbildung 5 zeigt einen typischen defekten Code.

Wenn diese Task (‘Thread’) vergisst, ihr Lock wieder freizugeben, müssen andere Tasks für unbestimmte Zeit darauf warten. Die Task selbst könnte sogar blockiert werden, wenn sie später versucht, das Lock wieder zu verwenden.

Was statische Analysetools heute noch nicht leisten können

Statische Analysetools können heute schon etliche Multitaskingfehler entdecken und werden in der Zukunft sicher noch effizienter arbeiten. Sie können z.B. noch keine Nachrichten nachverfolgen, die über den Queueing-Mechanismus eines Betriebssystems zwischen den Tasks ausgetauscht werden. Das Nachrichtenversenden wird besonders in hochkomplexen Systemen vermehrt eingesetzt, z.B. für den Einsatz in verteilten und Multicore-Umgebungen, doch sind statische Analysatoren heute technisch noch nicht in der Lage, Datenwerte nachzuverfolgen, wenn sie über eine Messaging-Funktion zwischen den Tasks ausgetauscht werden.

Andererseits könnte das Auffinden von nur einer Race Condition, einem Deadlock oder einem Lockout die Ausgaben für ein statisches Analysetool rechtfertigen, wenn man den enormen finanziellen und zeitlichen Aufwand für das Aufspüren solcher Defekte mit herkömmlichen Test- und Debugtools betrachtet.

Literaturhinweise:

Boehm, B., “Software Engineering Economics”,

1981, ISBN: 0138221227

DO-178B, „Software Considerations in Airborne Systems and Equipment Certification“, RCTA, December 1992.

Inhalt des Artikels:

Kommentar zu diesem Artikel abgeben

Schreiben Sie uns hier Ihre Meinung ...
(nicht registrierter User)

Kommentar abschicken
copyright

Dieser Beitrag ist urheberrechtlich geschützt. Sie wollen ihn für Ihre Zwecke verwenden? Infos finden Sie unter www.mycontentfactory.de (ID: 285126 / Software-Implementierung)