Race skick

Ett race condition , även en tävling  [ 1 ]  , är ett designfel i ett flertrådigt system eller applikation, där driften av systemet eller applikationen beror på i vilken ordning delar av koden exekveras. Felet har fått sitt namn från ett liknande konstruktionsfel i elektroniska kretsar (se signalracing ).

Termen race condition syftar på ingenjörsjargong och är resultatet av en slarvig bokstavlig översättning av den engelska motsvarigheten. I en mer rigorös akademisk miljö är det vanligt att använda termen samtidighetsosäkerhet .

Ett tävlingstillstånd är ett "flytande" fel ( heisenbug ), som dyker upp vid slumpmässiga tidpunkter och "försvinner" när du försöker lokalisera det.

Möjliga konsekvenser

På grund av okontrollerad åtkomst till delat minne kan ett racetillstånd leda till helt andra fel som kan uppstå vid oförutsägbara tidpunkter, och ett försök att replikera felet i felsökningssyfte med liknande driftsförhållanden kan misslyckas.

De huvudsakliga konsekvenserna kan vara:

Therac-25 fall

Strålbehandlingsmaskinen Therac -25 var den första medicinska enheten i USA som enbart förlitade sig på programvara för säkerhet . Den här enheten fungerade i tre lägen:

  1. Elektronterapi : Elektronpistolen bestrålar patienten direkt; datorn ställer in elektronenergin från 5 till 25 MeV .
  2. Röntgenterapi : En elektronpistol bestrålar ett volframmål och patienten bestrålas med röntgenstrålar som passerar genom en konformad diffusor. I detta läge är elektronenergin konstant: 25 MeV .
  3. I det tredje läget fanns ingen strålning. En stålreflektor placeras i elektronernas väg (vid en olycka), och strålningen simuleras av ljus . Detta läge används för att korrekt rikta strålen till den ömma punkten.

Dessa tre lägen ställdes in av en roterande skiva, i vilken det fanns ett hål med avböjande magneter för elektronisk terapi, och ett mål med en diffusor för röntgen. På grund av ett kapplöpningsförhållande mellan styrprogrammet och tangentbordsmotorn hände det ibland att i röntgenterapiläget var skivan i "Electron therapy"-läget och patienten bestrålades direkt med en 25 MeV elektronstråle, vilket ledde till överexponering. Samtidigt visade sensorerna "Noll dos", så att operatören kunde upprepa proceduren, vilket förvärrade situationen. Som ett resultat dog minst två patienter.

En del av koden togs från Therac-6 och Therac-20. Samtidigt hade Therac-6 ingen röntgenbehandling, och Therac-20 hade säkerhetsåtgärder för hårdvara som förhindrade strålningen från att slås på när disken var i fel position.

Exempel

Tänk på ett kodexempel (i Java ).

flyktig int x ; // Tråd 1: while ( ! stop ) { x ++ ; } // Tråd 2: while ( ! stop ) { if ( x % 2 == 0 ) System . ut . println ( "x=" + x ); }

Låt x=0. Anta att programmet körs i följande ordning:

  1. If-satsen i tråd 2 testar x för paritet.
  2. " x++ "-satsen i tråd 1 ökar x med en.
  3. Utdatasatsen i tråd 2 matar ut " x=1 " även om variabeln verkar vara paritetskontrollerad.

Lösningar

Lokal kopia

Det enklaste sättet att lösa detta är att kopiera variabeln x till en lokal variabel. Här är den korrigerade koden:

// Tråd 2: while ( ! stop ) { int cached_x = x ; if ( cachad_x % 2 == 0 ) System . ut . println ( "x=" + cachad_x ); }

Naturligtvis fungerar denna metod endast när det bara finns en variabel och kopiering görs i en maskininstruktion.

Synkronisering

En mer komplex och "dyrare", men också mer universell lösningsmetod är trådsynkronisering , nämligen:

int x ; // Tråd 1: while ( ! stop ) { synchronized ( someObject ) { x ++ ; } } // Tråd 2: while ( ! stop ) { synchronized ( someObject ) { if ( x % 2 == 0 ) System . ut . println ( "x=" + x ); } }

Här händer innan semantik inte kräver nyckelordet volatile.

Kombinerat sätt

Anta att det finns två variabler (och nyckelordet volatilehar ingen effekt), och den andra tråden System.out.printlnhar mer komplex bearbetning istället. I det här fallet är båda metoderna otillfredsställande: den första, eftersom en variabel kan ändras medan den andra kopieras; det andra beror på att för mycket kod är synkroniserad.

Dessa metoder kan kombineras genom att kopiera "farliga" variabler i ett synkroniserat block. Å ena sidan kommer detta att ta bort begränsningen för en maskininstruktion, å andra sidan låter det dig bli av med för stora synkroniseringsblock.

flyktig int x1 , x2 ; // Tråd 1: while ( ! stop ) { synchronized ( someObject ) { x1 ++ ; x2 ++ ; } } // Tråd 2: while ( ! stop ) { int cached_x1 , cached_x2 ; synchronized ( someObject ) { cached_x1 = x1 ; cachad_x2 = x2 ; } if (( cachad_x1 + cachad_x2 ) % 100 == 0 ) DoSomethingComplicated ( cachad_x1 , cachad_x2 ); }

Det finns inga uppenbara sätt att upptäcka och fixa tävlingsförhållanden. Det bästa sättet att bli av med raser är att korrekt designa ett multitasking-system.

Hackar genom att utnyttja rasförhållandena

Det finns en klass av buggar (och typer av attacker som utnyttjar dem) som tillåter ett  oprivilegierat program att påverka driften av andra program genom möjligheten att ändra offentliga resurser (vanligtvis temporära filer  ; filen är tillgänglig för skrivning av hela eller delar av användare av systemet på grund av en programmerares misstag.

Det attackerande programmet kan förstöra innehållet i filen, få offerprogrammet att krascha, eller, genom att ändra data, tvinga programmet att utföra någon åtgärd på nivån av dess privilegier.

Det är av denna anledning som programvara med allvarliga säkerhetskrav, såsom webbläsaren , använder slumptal av kryptografisk kvalitet för att namnge temporära filer.

Anteckningar

  1. Raymond, Eric S. Konsten att programmera Unix/översättning. från engelska. - M . : Förlag " Williams ", 2005. - S. 202. - 544 sid. — ISBN 5-8459-0791-8 .
  2. ↑ 1 2 3 4 Greg Kroah-Hartman, Alessandro Rubini, Jonathan Corbet. Kapitel 5. Samtidighets- och rasförhållanden // Linux-enhetsdrivrutiner . - 3:e upplagan. - O'Reilly Media, Inc., 2005. - ISBN 0596005903 . Arkiverad 12 april 2019 på Wayback Machine

Se även