Ogólnie rzecz biorąc, nie sądzę, że możesz niestety. (Niektóre systemy operacyjne mogą to zapewniać, ale nie znam tych, które znam.)
Dokument referencyjny dotyczący limitów zasobów: getrlimit
z POSIX 2008.
Weźmy na przykład limit procesora RLIMIT_CPU
.
- Jeśli proces przekroczy miękki limit, zostanie wysłany
SIGXCPU
- Jeśli proces przekroczy twardy limit, otrzyma zwykły
SIGKILL
Jeśli potrafisz wait()
w swoim programie, możesz stwierdzić, czy został zabity SIGXCPU
. Ale nie można było odróżnić SIGKILL
wysłanego za złamanie twardego limitu od zwykłego starego zabójstwa z zewnątrz. Co więcej, jeśli program obsługuje XCPU
, nie zobaczysz tego nawet z zewnątrz.
To samo dotyczy RLIMIT_FSIZE
. Widać SIGXFSZ
od wait()
stanu, jeśli program nie poradzić. Ale gdy limit rozmiaru pliku zostanie przekroczony, jedyną rzeczą, która się zdarza, jest to, że kolejne operacje we / wy, które spróbują ponownie przetestować ten limit, po prostu otrzymają EFBIG
- zostanie to obsłużone (lub niestety) wewnętrznie przez program. Jeśli program działa SIGXFSZ
tak samo jak powyżej - nie będziesz o tym wiedział.
RLIMIT_NOFILE
? Cóż, nawet nie dostajesz sygnału. open
i przyjaciele właśnie wracają EMFILE
do programu. Nie przeszkadza to w inny sposób, więc zawiedzie (lub nie) w jakikolwiek sposób, aby zakodować go w takiej sytuacji.
RLIMIT_STACK
? Dobry stary SIGSEGV
, nie można go odróżnić od wyniku z innych powodów, aby go dostarczyć. (Będziesz wiedział, że to właśnie zabiło proces, ze wait
statusu).
RLIMIT_AS
i RLIMIT_DATA
po prostu zrobi, malloc()
a kilka innych zacznie się nie powieść (lub otrzyma, SIGSEGV
jeśli limit AS zostanie przekroczony podczas próby rozszerzenia stosu w systemie Linux). O ile program nie jest bardzo dobrze napisany, prawdopodobnie w tym momencie prawdopodobnie losowo się nie powiedzie.
W skrócie, ogólnie mówiąc, awarie albo nie różnią się wyraźnie od innych przyczyn śmierci procesowej, więc nie możesz być pewien, albo można je całkowicie obsłużyć z programu, w którym to przypadku decyduje, czy / kiedy / jak będzie przebiegać, nie ty z zewnątrz.
O ile mi wiadomo, możesz napisać trochę kodu, który rozwidla twój program, czeka na niego i:
- sprawdź status wyjścia w celu wykrycia
SIGXCPU
i SIGXFSZ
(AFAIK, sygnały te będą generowane przez system operacyjny tylko w przypadku problemów z ograniczeniem zasobów). W zależności od swoich potrzeb, można założyć, że SIGKILL
i SIGSEGV
były również związane z ograniczeniami zasobów, ale to jest trochę odcinku.
- spójrz na to, co możesz uzyskać ze
getrusage(RUSAGE_CHILDREN,...)
swojej implementacji, aby uzyskać wskazówki na temat innych.
Mogą istnieć narzędzia specyficzne dla systemu operacyjnego, które mogą w tym pomóc (być może rzeczy takie jak ptrace
Linux lub Solaris dtrace
), lub ewentualnie techniki typu debuggera, ale będzie to jeszcze bardziej związane z konkretną implementacją.
(Mam nadzieję, że ktoś inny odpowie magiczną rzeczą, której jestem całkowicie nieświadomy.)
malloc
ale niestety nie rozwiązuje to ogólnie problemu z pamięcią, ponieważ ogólnie chodzi o wywołanie systemowebrk
(mam rację?).LD_PRELOAD
ing to granicę dla „nie modyfikujących proces” przymusu, a to pomoże trochę, ale nie naprawdę -malloc
,brk
,sbrk
immap
nie uda sięENOMEM
dokładnie tak, jakby naprawdę byli w niskim sytuacji pamięci (ale znacznie poniżej limitów pamięci). Limit czasu jest takiRLIMIT_CPU
, że nie znam limitu czasu naściennego.brk
. Jak widzę, wymaganie „program nie obsługuje sygnałów X, Y, Z ...” rozwiąże problemy SIGXCPU, SIGXFSZ, SIGSEGV, dzięki waitpid (Jeśli się mylę, proszę mnie poprawić).brk
. Jak widzę, wymaganie „program nie obsługuje sygnałów X, Y, Z ...” rozwiąże problemy SIGXCPU, SIGXFSZ, SIGSEGV, dzięki waitpid. Czy mam rację?Obecnie pracuję nad tym samym zagadnieniem. Byłem w stanie znaleźć częściowe rozwiązanie tego problemu. Użyłem susbsystemu audytu . Możesz śledzić pracę w [1].
[1] https://github.com/PaulDaviesC/Logging-limits.conf
źródło