Nasıl kontrol edilir, hangi sınır aşıldı? (Ulimit nedeniyle işlem sonlandırıldı.)


11

İşlemin ulimited ortamda çalıştığını varsayalım:

(
ulimit  ... -v ... -t ... -x 0 ...
./program
)

Program sonlandırıldı.

Bunun birçok nedeni olabilir: bellek / zaman / dosya sınırı aşıldı; sadece basit segfault; veya dönüş kodu 0 ile normal sonlandırma.

Programı değiştirmeden program sonlandırmanın nedenini nasıl kontrol edebilirim?

PS Yani "ikili verildiğinde". Belki bazı sarıcı (ptrace-ing vb) yardımcı olabilir?

Yanıtlar:


6

Genel olarak, ne yazık ki yapabileceğinizi sanmıyorum. (Bazı işletim sistemleri bunu sağlayabilir, ancak bunu desteklediğini bildiklerimin farkında değilim.)

Kaynak sınırları için referans dokümanı: getrlimitPOSIX 2008'den.

Örneğin CPU limitini ele alalım RLIMIT_CPU.

  • İşlem yumuşak sınırı aşarsa, SIGXCPU
  • Süreç zor sınırı aşarsa, SIGKILL

wait()Programınız üzerinde yapabiliyorsanız , tarafından öldürülüp öldürülmediğini anlayabilirsiniz SIGXCPU. Ancak SIGKILL, sert sınırın ihlali nedeniyle gönderilen bir gönderimi dışarıdan gelen eski bir öldürmeden ayırt edemezdiniz . Dahası, program ele alırsa XCPU, bunu dışarıdan bile göremezsiniz.

Aynı şey RLIMIT_FSIZE. Program işlemezse SIGXFSZ, wait()durumunu görebilirsiniz . Ancak dosya boyutu sınırı aşıldığında, gerçekleşen tek şey, bu sınırı tekrar test etmeye çalışan daha fazla I / O'nun basitçe alacağıdır EFBIG- bu, program tarafından dahili olarak ele alınacaktır (veya maalesef değil). Program SIGXFSZyukarıdaki gibi çalışıyorsa, bunu bilmezsiniz.

RLIMIT_NOFILE? Bir sinyal bile almýyorsun. openve arkadaşlar EMFILEprograma geri dönüyorlar . Aksi halde rahatsız edilmez, bu nedenle bu durumda başarısız olacak şekilde kodlanırsa başarısız olur (veya olmaz).

RLIMIT_STACK? İyi yaşlı SIGSEGV, bir tane almak için diğer nedenlerin puanından ayırt edilemez. (Ancak, durumdan süreci öldüren şeyin bu olduğunu bileceksiniz wait.)

RLIMIT_ASve RLIMIT_DATAsadece malloc()birkaçı başarısız olur ve başarısızlık başlar (veya SIGSEGVLinux'ta yığını genişletmeye çalışırken AS sınırına ulaşılırsa alır). Program çok iyi yazılmadığı sürece, muhtemelen bu noktada oldukça rastgele başarısız olacaktır.

Kısacası, genel olarak, başarısızlıklar ya diğer süreç ölüm nedenlerinden gözle görülür şekilde farklı değildir, bu yüzden emin olamazsınız ya da tamamen programdan ele alınabilir, bu durumda eğer değil, ne zaman / nasıl ilerlediğine karar verir, dışarıdan.

Bildiğim kadarıyla yapabileceğiniz en iyi program çatalları, üzerinde bekleyen kod biraz yazmak ve:

  • algılanacak çıkış durumunu kontrol edin SIGXCPUve SIGXFSZ(AFAIK, bu sinyaller yalnızca işletim sistemi tarafından kaynak sınırı sorunları için üretilecektir). Tam ihtiyaçları bağlı olarak, farz olabilir SIGKILLve SIGSEGVaynı zamanda kaynak limitleri ile ilgili idi, ama bu streç biraz bu.
  • getrusage(RUSAGE_CHILDREN,...)diğerleri hakkında bir ipucu almak için uygulamanızdan neler elde edebileceğinize bakın .

İşletim sistemine özgü tesisler burada yardımcı olabilir (muhtemelen ptraceLinux veya Solaris gibi şeyler dtrace) veya muhtemelen hata ayıklayıcı türü teknikler olabilir, ancak bu sizin özel uygulamanızla daha da bağlantılı olacaktır.


(Başka birinin tamamen bilmediğim sihirli bir şeyle cevap vermesini umuyorum.)


Tamam. Sadece bu üç tanesine ne dersiniz: (Mem) bellek sınırını aşan, (Zaman) zaman sınırını, (Err) diğer hatayı? Sarmalayıcı yapmayı biliyorum mallocama maalesef genel olarak hafıza problemini çözmüyor, çünkü genel olarak sistem çağrısı ile ilgili brk(doğru mu?).
Grzegorz Wierzowiecki

1
Programı kontrol etmezseniz malloc'yu kaydırmak yardımcı olmaz. Eğer gibi kesmek bahsediyorsan LD_PRELOADsenin "süreci değiştirerek değil" kısıtlama söz konusu en sınırı ing ve biraz yardımcı, ama gerçekten olacak - malloc, brk, sbrkve mmapbaşarısız olur ENOMEMEğer gerçekten bir bellek durumda olduğumuzu tam olarak sanki (ancak bellek sınırlarının çok altında). Zaman sınırı, RLIMIT_CPUbir duvar saati zaman sınırı bilmiyorum.
Mat

Beni temin ettiğin için teşekkürler brk. Gördüğüm gibi, gereksinim 'program X, Y, Z ... sinyallerini işlemiyor', waitpid sayesinde SIGXCPU, SIGXFSZ, SIGSEGV sorunlarını çözecektir (Yanlışsam, lütfen beni düzeltin).
Grzegorz Wierzowiecki

1
SIGSEGV, kaynak sınırı ihlali olmayan durumlarda ortaya çıkabilir (boş işaretçi dereference onu yükselten en yaygın şeydir) - buna neden olan bir ulimit vuruşu olduğundan emin olamazsınız.
Mat

Beni temin ettiğin için teşekkürler brk. Gördüğüm gibi, gereksinim 'program X, Y, Z ... sinyallerini işlemiyor', waitpid sayesinde SIGXCPU, SIGXFSZ, SIGSEGV sorunlarını çözecek. Haklı mıyım?
Grzegorz Wierzowiecki

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.