Závodní podmínky

Spornost , také konkurence  [ 1 ]  , je chyba návrhu ve vícevláknovém systému nebo aplikaci, ve které provoz systému nebo aplikace závisí na pořadí, ve kterém jsou části kódu vykonávány. Chyba dostala svůj název podle podobné konstrukční chyby v elektronických obvodech (viz závodění signálů ).

Termín race condition odkazuje na inženýrský žargon a je výsledkem nedbalého doslovného překladu anglického ekvivalentu. V přísnějším akademickém prostředí je obvyklé používat termín nejistota souběžnosti .

Spor je „plovoucí“ chyba ( heisenbug ), která se objevuje v náhodných časech a „zmizí“, když se ji pokusíte lokalizovat.

Možné důsledky

Kvůli nekontrolovanému přístupu ke sdílené paměti může spor vést ke zcela odlišným chybám, které mohou nastat v nepředvídatelných časech, a pokus o replikaci chyby pro účely ladění s podobnými provozními podmínkami může selhat.

Hlavní důsledky mohou být:

Pouzdro Therac-25

Zařízení pro radiační terapii Therac-25 bylo prvním lékařským zařízením ve Spojených státech , které se z hlediska bezpečnosti spoléhalo pouze na software . Toto zařízení pracovalo ve třech režimech:

  1. Elektronová terapie: Elektronová pistole přímo ozařuje pacienta; počítač nastaví energii elektronu od 5 do 25 MeV .
  2. Rentgenová terapie: Elektronová pistole ozařuje wolframový terč a pacient je ozařován rentgenovými paprsky procházejícími kuželovitým difuzorem. V tomto režimu je energie elektronu konstantní: 25 MeV .
  3. Ve třetím režimu nedošlo k žádné radiaci. V dráze elektronů je umístěn ocelový reflektor (pro případ havárie) a záření je simulováno světlem . Tento režim se používá k přesnému nasměrování paprsku na bolavé místo.

Tyto tři režimy nastavoval otočný disk, ve kterém byl otvor s vychylovacími magnety pro elektronickou terapii a terč s difuzorem pro rentgen. V důsledku závodního stavu mezi řídicím programem a motorem klávesnice se občas stalo, že v režimu RTG terapie byl disk v poloze „Elektronová terapie“ a pacient byl přímo ozářen elektronovým paprskem 25 MeV, který vedlo k přeexponování. Senzory zároveň zobrazovaly „Nulovou dávku“, takže operátor mohl postup zopakovat, což situaci ještě zhoršilo. V důsledku toho zemřeli nejméně dva pacienti.

Část kódu byla převzata z Therac-6 a Therac-20. Současně Therac-6 neměl rentgenovou terapii a Therac-20 měl hardwarová bezpečnostní opatření, která zabránila zapnutí záření, když byl disk ve špatné poloze.

Příklad

Zvažte příklad kódu (v Javě ).

volatilní int x ; // Vlákno 1: while ( ! stop ) { x ++ ; } // Vlákno 2: while ( ! stop ) { if ( x % 2 == 0 ) System . ven . println ( "x=" + x ); }

Nechť x=0. Předpokládejme, že se program spustí v následujícím pořadí:

  1. Příkaz if ve vláknu 2 testuje x na paritu.
  2. Příkaz " x++ " ve vláknu 1 zvyšuje x o jednu.
  3. Výstupní příkaz ve vláknu 2 vypíše " x=1 ", i když se zdá, že proměnná je zkontrolována paritou.

Řešení

Místní kopie

Nejjednodušší způsob, jak to vyřešit, je zkopírovat proměnnou x do lokální proměnné. Zde je opravený kód:

// Vlákno 2: while ( ! stop ) { int cached_x = x ; if ( cached_x % 2 == 0 ) Systém . ven . println ( "x=" + cached_x ); }

Tato metoda přirozeně funguje pouze v případě, že existuje pouze jedna proměnná a kopírování se provádí v jedné strojové instrukci.

Synchronizace

Složitější a „dražší“, ale také univerzálnější metodou řešení je synchronizace vláken , konkrétně:

int x ; // Vlákno 1: while ( ! stop ) { synchronized ( someObject ) { x ++ ; } } // Vlákno 2: while ( ! stop ) { synchronizováno ( someObject ) { if ( x % 2 == 0 ) System . ven . println ( "x=" + x ); } }

Zde se děje předtím , než sémantika nevyžaduje klíčové slovo volatile.

Kombinovaný způsob

Předpokládejme, že existují dvě proměnné (a klíčové slovo volatilenemá žádný vliv) a druhé vlákno System.out.printlnmá místo toho složitější zpracování. V tomto případě jsou obě metody neuspokojivé: první, protože jedna proměnná se může měnit, zatímco se druhá kopíruje; za druhé je synchronizováno příliš mnoho kódu.

Tyto metody lze kombinovat kopírováním „nebezpečných“ proměnných v synchronizovaném bloku. Na jednu stranu to odstraní omezení na jednu strojovou instrukci, na stranu druhou vám to umožní zbavit se příliš velkých synchronizačních bloků.

volatilní int x1 , x2 ; // Vlákno 1: while ( ! stop ) { synchronized ( someObject ) { x1 ++ ; x2 ++ ; } } // Vlákno 2: while ( ! stop ) { int cached_x1 , cached_x2 ; synchronized ( someObject ) { cached_x1 = x1 ; cached_x2 = x2 ; } if (( cache_x1 + cache_x2 ) % 100 == 0 ) DoSomethingComplicated ( cached_x1 , cached_x2 ); }

Neexistují žádné zřejmé způsoby, jak zjistit a opravit podmínky závodu. Nejlepší způsob, jak se zbavit ras, je správně navrhnout multitaskingový systém.

Hackuje zneužitím rasových podmínek

Existuje třída chyb (a typy útoků, které je využívají), které umožňují  neprivilegovanému programu ovlivňovat činnost jiných programů prostřednictvím schopnosti měnit veřejné zdroje (obvykle dočasné soubory  ; soubor je k dispozici pro zápis všemi nebo částmi uživatelů systému v důsledku chyby programátora.

Útočící program může zničit obsah souboru a způsobit selhání programu oběti, nebo změnou dat donutit program provést nějakou akci na úrovni jeho oprávnění.

To je důvod, proč software s vážnými bezpečnostními požadavky, jako je webový prohlížeč , používá k pojmenování dočasných souborů náhodná čísla kryptografické kvality.

Poznámky

  1. Raymond, Eric S. The Art of Unix Programming / přel. z angličtiny. - M . : Nakladatelství " Williams ", 2005. - S. 202. - 544 s. — ISBN 5-8459-0791-8 .
  2. ↑ 1 2 3 4 Greg Kroah-Hartman, Alessandro Rubini, Jonathan Corbet. Kapitola 5. Podmínky souběžnosti a rasy // Ovladače zařízení pro Linux . - 3. vydání. - O'Reilly Media, Inc., 2005. - ISBN 0596005903 . Archivováno 12. dubna 2019 na Wayback Machine

Viz také