Race Condition

Race Condition Nedir?

“Race condition ya da diğer adıyla race hazard; veri çıktısının kontrol
edilemeyen olayların sıralama ya da zamanlamasına bağlı olduğu elektronik,
yazılımsal ya da başka bir sistemin davranışıdır.
Programın işleyişi programcının amacı dışında bir sıralamaya bağlı ilerliyorsa,
bu programda kusur(bug) olduğu anlamına gelir.
Race condition durumu genellikle elektronik sistemlerin mantıksal devrelerinde
ve bilgisayarların çoklu kullanım(multithreading) sağlayan ya da
dağıtık sistemleri oluşturan yazılımlarında oluşur.” /wiki/Race_condition

Wikipedia sayfasında bulunan açıklamaya göre Race Condition, birbirinden ayrı
çalışan sistemlerin bir veriyi işleme ve iletmesi sırasındaki uyumsuzluğundan(asynchronization)
kaynaklanan bir davranış biçimidir.

Dosya Sistemlerinde

Dosya sistemlerinde(File Systems) iki ya da daha fazla program bir dosyaya
ulaşmak üzere birbiriyle çakışabilir ve bu durum dosyadaki verinin bozulmasına(corrupt)
neden olabilir. Bu sorunu giderebilmek adına kullanılan en yaygın yöntem dosya kilitleme(
File Locking) yöntemidir. Dosya kilitleme mekanizması, bir bilgisayar dosyasına
belirlenen süre içinde sadece bir kullanıcı ya da işlemin(process) erişmesini sağlayan
yöntemdir. Aynı anda birden fazla kullanıcı ya da işlemin erişimini engelleyerek dosyanın
zarar görmesini(corrupt) engeller

Dosya sistemindeki Race Condition senaryosu;
1. İşlem A, “Müşteri” isimli dosyadaki bir müşterinin hesap bakiyesini okur ve
hafızasına alır.
2. İşlem B, “Müşteri” dosyasındaki aynı müşterinin hesap bakiyesini okur ve bu
bilgiyi hafızasına alır.
3. İşlem A, hafızasındaki bilginin hesap bakiyesi değerini değiştirir ve “Müşteri”
dosyasında müşterinin bilgileri arasına kaydeder.
4. Hafızasında müşterinin eski bilgilerini tutan İşlem B bu bilgileri değiştirir ve
“Müşteri” dosyasında müşterinin bilgisi olarak kaydeder.
5. “Müşteri” dosyasındaki değişikliği yapan son kullanıcı İşlem B olduğu için
İşlem A’nın kaydettiği bilgiler geçersizdir ve “Müşteri” dosyasında müşteri bilgilerinde
yer alan hesap bakiyesi ve telefon numarası bilgileri İşlem B’nin değiştirdiği ve kayıt
ettiği bilgilerdir.

İnternet Ağlarında

Dağıtık sistemlerde bir verinin birden fazla sistem tarafından değiştirilmesi söz
konusudur. Bu işlemler sırasında race condition ile karşılaşılması muhtemeldir. Örnek
olarak dağıtık bir chat ağı olan IRC ele alırsak; bir kullanıcı yeni bir kanal başlattığında
bu kanalın operatör haklarına sahip olur. Ayrı sunucularda bulunan iki kullanıcı aynı isimli
kanalı aynı anda açmak isterse, ikisi de aynı kanalın operatör haklarına sahip olur. Bu
sorun çeşitli IRC sunucu uygulamalarıyla büyük oranda çözülmüştür.

Kontrol Zamanından Kullanım Zamanına(Time of
Check to Time of Use)

Kullanıcı ve yöneticinin olduğu bir web uygulaması düşünelim. Bu web uygulamasında
kullanıcı sayfa üzerinde değişiklik yapabilme yetkisine, yönetici de kullanıcının
değişiklik yetkisini açıp kapama yetkisine sahip olsun.
1. Yönetici, kullanıcıya değişiklik yapma yetkisi verir
2. Kullanıcı web sayfasını düzenleme işlemini başlatır
3. Yönetici kullanıcının değişiklik yapma yetkisini kısıtlar
4. Kullanıcı değişikliği tamamlar ve yaptığı değişikliği kaydeder
5. Yönetici, kullanıcının değişiklik yapma yetkisini kısıtlamasına rağmen kullanıcının
yaptığı kayıt işlemi tamamlanır.

UNIX işletim sistemlerinin dosya sistemlerinde, veri tabanı işlevlerinin hatalı kullanımı
sonucunda ve yerel UNIX domain soketlerinde bu türde bir race condition oluşma
ihtimali daha olağandır.

UNIX’de bulunan setuid programında oluşan race condition, C kodunda incelenebilir.
1. if (access(“file”, W_OK) !=0) {
2. exit(1);
3. }
4. fd = open(“file”, O_WRONGLY);
5. write(fd, buffer, sizeof(buffer));
“access()” fonksyonu, setuid programını çalıştıran kullanıcının yazma hakkı olup
olmadığını kontrol etmesi gerekir.

Bağlantı Sertifikası Kontrolü Sırasında

Bir web uygulamasında kullanılan sertifikanın uygunluğu ilk bağlantı sırasında
doğrulanır fakat bağlantıdan sonra sertifika iptal(revoke) edilirse, uygulamanın güvenliği
açısından tehdit oluşur. Bu sorunu gidermek amacıyla her bağlantı sırasında kontrol
edilirse bu tür bir tehditin rahatlıkla önüne geçilebilir.

Sinyal İşleyici Sistemlerde

Senkronize olmayan çalışma prensibi sebebiyle sinyal işleyici sistemlerde race
condition durumu ile karşılaşılma ihtimali çok yüksektir.
Race condition durumu, yeniden girişli olmayan(non-reentrant) fonksiyonların
veya durum-duyarlı(state-sensitive) işlemlerin zamansız kullanımı sırasında istismar
edilebilir.

Java ile Threading Sırasında Oluşan Race Condition

Java ile yazılan bir uygulamalarda race condition sorununu gidermek .NET ile
yazılmış bir koda göre daha kolay.

RCRaceCondition.java
1. public class RCRaceCondition {
2. public static void main(String[] args) {
3. RCBankAccount rcAccount = new RCBankAccount(“RCccountNumber”);
4. for (int i = 0; i < 100; i++) { 5. RCTransaction t = new RCTransaction(rcAccount, 6. RCTransaction.TransactionType.DEPOSIT_MONEY, 100); 7. t.start(); } 8. for (int i = 0; i < 100; i++) { 9. RCTransaction t = new RCTransaction(rcAccount, 10. RCTransaction.TransactionType.WITHDRAW_MONEY, 50); 11. t.start(); } // Bütün threadlerin işlemlerini tamamlaması için 1dk bekleme süresi. 12. try { Thread.sleep(1000); } catch(InterruptedException e) { System.out.println(e); } 13. System.out.println(“Final Account Balance: ” + rcAccount.getAccountBalance()); } } RCRaceCondition.java kodları genel olarak incelendiğinde finansal işlemlerin gerçekleşme biçimini belirliyor. Bu kodlar arasında race condition sorunu yaratan bir satır bulunmuyor. RCTransaction.java 1. class RCTransaction extends Thread { 2. public static enum TransactionType { 3. DEPOSIT_MONEY(1), WITHDRAW_MONEY(2); 4. private TransactionType(int value) { } } 5. private TransactionType transactionType; 6. private RCBankAccount rcAccount; 7. private double rcAmount; 8. public RCTransaction(RCBankAccount rcAccount, TransactionType transactionType, 9. double rcAmount) { 10. this.transactionType = transactionType; 11. this.rcAccount = rcAccount; 12. this.rcAmount = rcAmount; } 13. public void run() { 14. switch (this.transactionType) { 15. case DEPOSIT_MONEY: 16. depositAmount(); 17. printBalance(); 18. break; 19. case WITHDRAW_MONEY: 20. withdrawAmount(); 21. printBalance(); 22. break; 23. default: 24. System.out.println(“NOT A VALID TRANSACTION”); 25. public void depositAmount() { this.rcAccount.depositAmount(this.rcAmount); } 26. public void withdrawAmount() { this.rcAccount.withdrawAmount(rcAmount); } 27. public void printBalance() { System.out.println(Thread.currentThread().getName() + 28. ” : TransactionType: ” + this.transactionType + “, Amount: ” + this.rcAmount); 29. System.out.println(“New Account Balance: ” + this.rcAccount.getAccountBalance()); } } RCTransaction.java kodları thread üzerinde işlemleri gerçekleştirme yarıyor. Bu dosyadaki kod satırları “Thread” sınıfı üzerinden türetilen “RCTransaction” sınıfının işlevini gösteriyor. “RCTransaction” çağırılmadığı sürece race condition sorunu yaratacak bir davranış içermiyor. Kullanılan Kaynaklar: https://en.wikipedia.org/wiki/Race_condition https://en.wikipedia.org/wiki/File_locking https://en.wikipedia.org/wiki/Time-of-check-to-time-of-use https://www.owasp.org/index.php/Race_Conditions http://www.c-sharpcorner.com/UploadFile/1d42da/race-conditions-in-threading-C-Sharp/ http://crunchify.com/have-you-noticed-race-condition-in-java-multithreading-concurrency-example-how-to-deal-with-it/ Sinan KİLCİ 04/06/2016