Bir Sinyalin Eyleminin Sonradan Hatırlanması
Önceki Sinyallerin Engellenmesi Sonraki
Bir Sinyalin Eyleminin Sonradan Hatırlanması
Bir sinyalin engellenmesini, kütüphane oluşumlarını kullanmak yerine daha sonra sinyalin engellenmediği bir sırada sınanacak bir değişkene sinyal eylemci içinde bir değer atamak suretiyle yapabilirsiniz. Bir örnek:
/* Bu değişkenin değeri sıfırdan farklıysa, o sinyal bekletiliyordur. */
volatile sig_atomic_t signal_pending;

/* Bir sinyal geldiğinde işleme sokulmayacaksa bu değişkenin değeri
   sıfırdan farklı olacaktır. */
volatile sig_atomic_t defer_signal;

void
handler (int signum)
{
  if (defer_signal)
    signal_pending = signum;
  else
    ... /* "Gerçekten" sinyal yakalanmış. */
}

...

void
update_mumble (int frob)
{
  /* Sinyallerin hemen etki etmesini engelleyelim. */
  defer_signal++;
  /* Şimdi kesmelerden korkmadan mumble'ı güncelleyelim. */
  mumble.a = 1;
  mumble.b = hack ();
  mumble.c = frob;
  /* mumble güncellendi.  Gelen herhangi bir sinyali işleme sokabiliriz. */
  defer_signal--;
  if (defer_signal == 0 && signal_pending != 0)
    raise (signal_pending);
}
Belli bir sinyalin geldiğinde signal_pending içinde nasıl saklandığına dikkat edin. Bu yolla, aynı mekanizmayı kullanarak farklı türdeki sinyalleri yakalayabiliriz.
Kodun önemli yerlerinde defer_signal değişkeninin değerini önce arttırıp sonra azaltıyoruz; böylece signal_pending sıfırdan farklıyken update_mumble çağrıldığında sadece update_mumble içinde değil ayrıca çağrıcı içinde de ertelenecektir. Bu nedenle, defer_signal sıfırdan farklı olduğunda signal_pending'e bakmıyoruz.
defer_signal'in arttırılması ve eksiltilmesi bir makine komutundan fazlasını gerektirir; bu nedenle işlemin tamamlanmamışken sinyal alınması ihtimal dahilindedir. Fakat bu herhangi bir soruna yolaçmaz. Arttırma ya da eksiltmenin başlamasından hemen önce bir sinyal gelirse bile çalışma bozulmayacaktır.
defer_signal'in signal_pending sınanmadan önce arttırılması ölümcül öneme sahiptir. Bu çözümü zor bir yazılım hatasından kaçınmayı sağlar. Eğer bu işlemleri aşağıdaki gibi farklı bir sırada yapmış olsaydık,
  if (defer_signal == 1 && signal_pending != 0)
    raise (signal_pending);
  defer_signal--;
if deyimi ile arttırım arasında gelen bir sinyal sonsuza kadar kaybolurdu. defer_signal'e sadece sinyal eylemci değer atasa ve yazılım bu değişkene baksa eylemci bu değişkene bakmazdı.
Bu çeşit yazılım hatalarına zamanlama hataları adı verilir. Yaygın olarak oluştukları halde yeniden üretilmeleri imkansız olduklarından özellikle kötü hatalardır. Bu hatayı üretemeyeceğinizden bir hata ayıklayıcı ile bu hataları bulamazsınız. Bu nedenle onlardan kaçınmak için özellikle büyük dikkat sarfetmelisiniz.
(defer_signal değişkenini sayaç olarak kullanıyorsanız kodu bu şekilde yazmak size daha kolay gelebilir. Normalde bu değişkenin signal_pending değişkeni ile birlikte sınanması gerekir. Her durumda bu sayacı sıfır değeri için sınamak, bir değeri için sınamaktan daha basittir. Eğer defer_signal değişkeni sayaç olarak kullanılmıyor ve sadece sıfır veya bir değerini alabiliyorsa, sınama sırası sınama işleminin karmaşıklığını pek etkilemez. Bu da defer_signal değişkenini sayaç olarak kullanmanın bir diğer getirisidir: Kodu yanlış sırada yazmak suretiyle bulunması zor olacak bir hata yapma şansınız azalır.)
Önceki Üst Ana Başlık Sonraki
Bekleyen Sinyallerin Sınanması Başlangıç Sinyalin Beklenmesi
Bir Linux Kitaplığı Sayfası