2015-10-13 31 views
11

Sistemimde (Ubuntu Linux, glibc), bir close aramasının man sayfası, dönebileceği çeşitli hata döndürme değerlerini belirtir. Ayrıca, close() 'ın dönüş değeri genel olarak geçerli ancak yine de ciddi bir programlama hatası olduğunu kontrol etmediğinden emin değil. Bir posix kapatma çağrısı başarısız olursa ne yapmalı?

ve dönüş değeri sadece teşhis için kullanılması gerektiğini, aynı zamanda

Not at

. Özellikle bir close() bir EINTR'den sonra tekrar denenmemelidir, çünkü bu durum başka bir evreden yeniden kullanılan bir tanımlayıcının kapanmasına neden olabilir. Bu nedenle, dönüş değerini göz ardı etmemeye veya aramayı yeniden denemeye izin verilmemelidir.

Verilen bakımdan, close() çağrı hatasını nasıl ele alabilirim?

Dosyaya bir şey yazarken hata olduysa, veri kaybını önlemek için bilgileri başka bir yere yazmayı denemeliyim.

Sadece dosyayı okuyorsam, başarısızlığı günlüğe kaydedebilir ve hiçbir şey olmamış gibi davranarak programa devam edebilir miyim? Herhangi bir uyarı, dosya tanıtıcı sızıntısı var mı, yoksa başka bir şey var mı?

+0

Düşünce. (http://unix.stackexchange.com/questions/231677/failing-close-system-call) Bazı durumlarda kapatma hataları mantıklıdır (örneğin, hatalı disk senk.). Bazı durumlarda başarısız olur. Aynı fiziksel dosyaya işaret eden veya bir boruyu kapatarak son örneği olmayan çoğaltılmış bir dosya tanıtıcısını kapatmak gibi, çünkü bunlar temel olarak çekirdek hatalarıdır, ancak daha aydınlanmış bir cevabı duymak isterim. – PSkocik

+1

FWIW, Raymond Chen'in bu genel durumu ele alalım: http://blogs.msdn.com/b/oldnewthing/archive/2008/01/07/7011066.aspx –

+0

Ne yaparsanız yapın, * her zaman kullanıcıya bildirin * . Sadece kimsenin bakmadığı bir iç kayıt dosyasına "giriş yapmak" yeterli değildir; Kullanıcının hinky olduğunu öğrenmesini istersiniz. GUI uygulamaları için kalıcı bir iletişim kutusu açabilirim. Komut satırı uygulamaları için standart hataya uyarı yazdım. Hizmetler için günlük dosyası yeterlidir. Bir dosyaya yazdıktan sonra 'close()' hatası oluşursa, dosyaya yazarken bir yazım hatasıyla karşılaşırsam tam olarak aynısını yapardım. –

cevap

6

, close hata denenecek ve close geçirilen fd bakılmaksızın bir hata oluşup oluşmadığını, close döndükten sonra her zaman geçersiz (kapalı) olduğu asla. Bazı durumlarda, bir hata verilerin kaybolduğunu (bazı NFS kurulumları) veya aygıtlar için olağandışı donanım koşullarını (örn. Bant tekrar sarılmayabilir) gösterebilir, bu nedenle veri kaybını önlemek için dikkatli olmak isteyebilirsiniz, ancak hiçbir zaman denememelisiniz. fd'yi tekrar kapatın. Teorik olarak, POSIX, closeEINTR ile başarısız olduğunda ve sistem uyuşmazlığı durumunda fd'nin açık kalacağı konusunda geçmişte belirsizdi. Durumu bilmek çok önemlidir (aksi takdirde çok iş parçacıklı programlarda çok tehlikeli olan fd sızıntıları veya çift kapanma hataları vardır), Austin Group issue #529 çözünürlüğü kesinlikle POSIX'in gelecek sürümleri için davranışı belirtmiştir, bu EINTR fd açık kalır.Bu, başka bir yerde EINTR tanımına uygun doğru davranıştır, ancak Linux bunu kabul etmeyi reddeder. (FWIW bunun için libc syscall sarmalayıcı seviyesinde mümkün olan kolay bir çözüm var; bkz. glibc PR #14627.) Neyse ki hiç bir zaman pratikte ortaya çıkmaz. Eğer bilgilendirici bulabilirsiniz

ilgili bazı sorular: Bu konuda da

+0

Yani EINTR'de fd açık kalırsa, tekrar kapatmayı denemek için bir hata olmaya devam ediyor mu? Bu durumda ne yapmalıyız?Geçersiz bir tanımlayıcının kapatılması, "EINVAL" i döndürmelidir, bu yüzden tekrar denemek için bir problem değildir (el kitabının diğer dosyalarla ilgili bilgi içermeyen açık dosya tanıtıcıları olmasına rağmen, diğer iş parçacığına sahipseniz, diğer iş parçacığı yalnızca bir açıklayıcıyı açarsa ne olur? Bir IO yönlendirmesinin ortası? --- Bu iki aşamalı bir prosedürdür. Hmmm ... makineyi çok zorlamaya çalışıyor muyuz? –

+0

@LuisColorado: (Değiştirilmiş) standardı uyarınca, "EINTR" de fd açık kalır. Ancak, Linux bunu onurlandırmıyor ve glibc onurlandırmadaki başarısızlık etrafında çalışmıyor. Cevabımdaki bağlantıları görün. Neyse ki, EINTR, zaten farkında olduğum gerçek dünya durumlarında Linux'ta 'yakın'da gerçekleşmez. –

+0

'EINTR',' NFS dosya sistemlerinde kapat (2) 'üzerinde, ağ bağlantılarında (çekirdek, aslında TCP/IP soketlerinde çekirdek, aslında diğer protokollerde değil, aynı zamanda, diğer protokollerde de olduğu gibi) ve her aygıtta kapanmak için el sıkışma gerekliliğini (son yakın şeyde, aygıt sürücüsüne bağlı olarak kapanmaya bağlı olarak) ve linux * mevcut olan * sadece * POSIX sistemi değildir. –

1

Her şeyden önce: EINTR tam olarak şu anlama gelir: Sistem çağrısı kesildi, bu close() numaralı çağrıda gerçekleşirse, yapabileceğiniz hiçbir şey yoktur.

Gerçek şu ki, bir dosyaya aitse, bu dosya muhtemelen bozuksa, close()'daki hatalar hakkında yapabileceğiniz fazla bir şey yoktur - dönüş değerine bağlı olarak. AFAIK, bir kapanışın yeniden denenebileceği tek durum, EBUSY, ancak bunu henüz görmedim. Yani

:

  • close() sonucu kontrol Eğer özellikle kesme dosya bozulması kaçırmak anlamına gelebilir değil.
  • Hataya bağlı olarak, çoğu zaman hiçbir şey yapamazsınız - başarısız olan bir , uygulamanızın kapsamı dışında bir şeylerin yanlış gittiği anlamına gelir. Uygulamada
+0

'EINTR', syscall'ın kesintiye uğradığı ve tekrar denenmeyeceği anlamına gelir, bu nedenle hiçbir şekilde çalıştırılmadı. Sistem çalışmadı, bu yüzden dosya tanıtıcı kapalı değil ve kapatılmalıdır. Sistem çağrılarının atomikliği ne durumda? Sistem çağrısı yapılmadıysa ve tanımlayıcıyı tekrar kapatamıyorsak, bu işlemi her seferinde bir tanımlayıcının sızıntısıyla birkaç kez tekrarlamaktan ne haber? Normalde, bloke eden çağrıların (close() gibi, normal dosyalar için değil) gerçekleştirilmesi, sadece ne yapıldığını çözer ve sadece atomisiteyi korumak için kaydedilen bağlamda bir longjmp (3) yapar. –

+0

@LuisColorado 'EINTR' sonra' close() 'yeniden denemek Linux hakkında iyi bir fikir değildir. Farklı bir fd'yi kapatabilir. –

+0

Aygıt sürücüsü yazarları her zaman yakın ilkel hakkında uyarılırlar, çünkü çalışmalarını donanım koşullarından bağımsız olarak yapması ve sabit bir ortam sağlaması gerekir. Bu, aygıt sürücüsü yazarlarının, bazı koşullara kadar aygıtın yanıt vermeyeceğini veya işaretlenemez olarak işaretlenmesini beklemek için bazen belleğe kilitlenmiş kaynakları bırakması gerektiği anlamına gelir, ancak işlem zamanın bağlantısını kesmiştir. Aygıt sürücülerinin normalde işletim sistemini yazan aynı kişiler tarafından yazılmadığını düşünün. Özellikle linux'dan konuşmuyorum, ama posix için, birçok farklı sistem anlamına geliyor. –

İlgili konular