Mam pewne problemy z serwerem dzisiaj i teraz sprowadziłem go do tego, że nie jest w stanie pozbyć się procesów, które dostają segfault.Uszkodzenie segmentacji samo wisi
Po tym, jak proces otrzyma błąd seg-fault, proces się zawiesi, a nie zostanie zabity.
Test, w wyniku którego powinien spowodować błąd Segmentation fault (core dumped)
.
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char **argv)
{
char *buf;
buf = malloc(1<<31);
fgets(buf, 1024, stdin);
printf("%s\n", buf);
return 1;
}
Skompiluj i ustaw uprawnienia za pomocą gcc segfault.c -o segfault && chmod +x segfault
.
Uruchomienie tego (i naciśnięcie klawisza Enter 1 raz) na problematycznym serwerze powoduje jego zawieszenie. Uruchomiłem to również na innym serwerze z tą samą wersją jądra (i większością tych samych pakietów), i otrzymuje on błąd seg-fault, a następnie kończy działanie.
Oto kilka ostatnich linii po uruchomieniu strace ./segfault
na obu serwerach.
Bad serwer
"\n", 1024) = 1
--- SIGSEGV {si_signo=SIGSEGV, si_code=SEGV_MAPERR, si_addr=0} ---
# It hangs here....
Praca serwer
"\n", 1024) = 1
--- SIGSEGV {si_signo=SIGSEGV, si_code=SEGV_MAPERR, si_addr=0} ---
+++ killed by SIGSEGV (core dumped) +++
Segmentation fault (core dumped)
[email protected] { ~ }# echo $?
139
Gdy zawiesza procesowe (po to są segfaulted), to jak to wygląda.
nie może^c it
[email protected] { ~ }# ./segfault
^C^C^C
Wejście ps aux
root 22944 0.0 0.0 69700 444 pts/18 S+ 15:39 0:00 ./segfault
cat/Proc/22944/stos
[<ffffffff81223ca8>] do_coredump+0x978/0xb10
[<ffffffff810850c7>] get_signal_to_deliver+0x1c7/0x6d0
[<ffffffff81013407>] do_signal+0x57/0x6c0
[<ffffffff81013ad9>] do_notify_resume+0x69/0xb0
[<ffffffff8160bbfc>] retint_signal+0x48/0x8c
[<ffffffffffffffff>] 0xffffffffffffffff
Kolejną zabawną rzeczą jest to, że nie mogę dołączyć do procesu składania w zawieszeniu strace
. Czyniąc to faktycznie sprawia, że zostaje zabity.
[email protected] { ~ }# strace -p 1234
Process 1234 attached
+++ killed by SIGSEGV (core dumped) +++
ulimit -c 0
jest sat i ulimit -c
, ulimit -H -c
i ulimit -S -c
wszystko pokazuje wartość wersję 0
- jądra:
3.10.0-229.14.1.el7.x86_64
- Distro wersja:
Red Hat Enterprise Linux Server release 7.1 (Maipo)
- bieganie w VMware
Serwer działa tak, jak powinien na wszystkich pozostałych elementach.
Aktualizacja Wyłączanie ABRT (systemctl stop abrtd.service
) rozwiązaniu problemu z procesów już wisiał po podstawowej wysypisko, a nowe procesy core-dumping. Ponowne uruchomienie abrt nie przywróciło problemu.
Aktualizacja 2016-01-26 Mamy problem, który wyglądał podobnie, ale nie do końca taki sam. Początkowy kod używany do testowania:
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char **argv)
{
char *buf;
buf = malloc(1<<31);
fgets(buf, 1024, stdin);
printf("%s\n", buf);
return 1;
}
został powieszony. Wyjście cat /proc/<pid>/maps
był
00400000-00401000 r-xp 00000000 fd:00 13143328 /root/segfault
00600000-00601000 r--p 00000000 fd:00 13143328 /root/segfault
00601000-00602000 rw-p 00001000 fd:00 13143328 /root/segfault
7f6c08000000-7f6c08021000 rw-p 00000000 00:00 0
7f6c08021000-7f6c0c000000 ---p 00000000 00:00 0
7f6c0fd5b000-7f6c0ff11000 r-xp 00000000 fd:00 14284 /usr/lib64/libc-2.17.so
7f6c0ff11000-7f6c10111000 ---p 001b6000 fd:00 14284 /usr/lib64/libc-2.17.so
7f6c10111000-7f6c10115000 r--p 001b6000 fd:00 14284 /usr/lib64/libc-2.17.so
7f6c10115000-7f6c10117000 rw-p 001ba000 fd:00 14284 /usr/lib64/libc-2.17.so
7f6c10117000-7f6c1011c000 rw-p 00000000 00:00 0
7f6c1011c000-7f6c1013d000 r-xp 00000000 fd:00 14274 /usr/lib64/ld-2.17.so
7f6c10330000-7f6c10333000 rw-p 00000000 00:00 0
7f6c1033b000-7f6c1033d000 rw-p 00000000 00:00 0
7f6c1033d000-7f6c1033e000 r--p 00021000 fd:00 14274 /usr/lib64/ld-2.17.so
7f6c1033e000-7f6c1033f000 rw-p 00022000 fd:00 14274 /usr/lib64/ld-2.17.so
7f6c1033f000-7f6c10340000 rw-p 00000000 00:00 0
7ffc13b5b000-7ffc13b7c000 rw-p 00000000 00:00 0 [stack]
7ffc13bad000-7ffc13baf000 r-xp 00000000 00:00 0 [vdso]
ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0 [vsyscall]
Jednak kod mniejszy c (int main(void){*(volatile char*)0=0;}
), aby wywołać segfault nie spowodować segfault i nie powiesić ...
Sprawdź zwracaną wartość 'malloc'. 100% pewności, że jest NULL. Ale 'malloc (1 << 31);' może faktycznie działać, jeśli> 2 GB wolnej pamięci jest dostępne. –
@Michael Walz: To jest pomysł. Ma to spowodować uszkodzenie. –
Czy możesz dać mi przykład? Nie wiem zbyt wiele o programowaniu w języku c/C++. Podany program przykładowy powinien powodować uszkodzenie. – xeor