Dün gece, Selenium ile yazdığım bir veri çekme botunu uzaktaki sunucuda çalıştırıp yatağa girdim. "Sabah güzel bir rapor hazır olur" diye düşünüyordum. Sabah baktım, bot hala çalışıyor ama hiçbir işlem yapmıyor! Terminalde sadece "Flag bekleniyor..." yazısı dönüp duruyordu. Kafayı yiyecektim.
Mantık basitti: Bot, bir işlem yapmadan önce `/tmp/process.lock` gibi bir flag dosyasının varlığını kontrol edecek, eğer dosya yoksa işlemi yapıp sonra onu silecekti. Başka bir cron job veya proses de işi bitirince o dosyayı silecekti. Meğerse o "başka proses" dosyayı silmeyi unutmuş! Bot da dosya var diye, onun silinmesini sonsuza kadar beklemeye başlamış.
StackOverflow'da bile böyle saçma bir deadlock aramak zorunda kaldım. Loglarda hiçbir hata yoktu, sadece bekliyordu. Şaka gibi ama, saatlerce ps aux ve lsof komutlarıyla hangi prosesin o lanet dosyayı tuttuğunu aradım.
Bash:
lsof /tmp/process.lock
Sonunda, dosyayı oluşturan eski bir test scriptinin arka planda zombie gibi kaldığını fark ettim. Çözüm olarak, botuma bir "zaman aşımı" mekanizması ekledim. Artık flag dosyası 5 dakikadan eskiyse, onu yok sayıp işleme devam ediyor veya dosyayı silip kendi işini yapıyor.
Python:
import os
import time
flag_file = "/tmp/process.lock"
timeout = 300 # 5 dakika
if os.path.exists(flag_file):
file_age = time.time() - os.path.getmtime(flag_file)
if file_age > timeout:
os.remove(flag_file) # Eskimiş kilidi kır
print("[B]Eski kilit temizlendi, devam ediliyor.[/B]")
else:
print("[B]Başka bir işlem devam ediyor, bekleniyor...[/B]")
exit()
else:
# İşleme başla
open(flag_file, 'w').close()
# ... işlemler burada ...
os.remove(flag_file) # İş bitince temizle
Bu olay bana şunu öğretti: Dış kaynaklara (dosya sistemi, ağ, başka bir proses) bağlı olan her türlü "lock" veya "flag" mekanizmasında MUTLAKA bir timeout ve recovery planın olmalı. Yoksa bir gün gelir, botun sonsuz bir bekleyişte donup kalır.
Siz de benzer bir "sonsuz bekleme" tuzağına düştünüz mü? Bu tarz proses koordinasyonu için flag dosyası dışında daha temiz yöntemleriniz var mı? (Mesela Redis lock fena değil gibi)