Simulation is ...

Virtual = Real

Flight Sim 자세히보기

ㆍ Linux

coredump, 세그먼트 폴트, segfault at 0 ip error 4 in libc-2.28.so

FlightSim 2023. 8. 9. 12:04
320x100

segmentation fault (core dumped)

이런 무시무시한 문구가 떴는데, 눈을 씻고 찾아봐도 coredump 파일을 찾을 수가 없었습니다. 분명 메시지는 coredump 파일 생성됐다고 써있는데 말이죠... 내눈이 잘못된건가, 아니면 내가 영어를 못하는건가.. 

그래서 제가 찾은 coredump를 찾는 몇가지 해결 방법을 알려드리도록 할게요. 

1. ulimit으로 core dump size를 확인

아래와 같은 명령어로 core file size를 확인합니다. 

# ulimit -a

0 이상이어야합니다. 그러니까 이 부분을 고쳐하겠죠. 0보다 크면 되긴하지만, unlimited로 바꿔보도록 합시다. 

# ulimit -c unlimited

 

위처럼 unlimited로 바뀐것을 알 수 있습니다. 이제 프로그램을 실행시키면 coredump 파일이 생성될 수도 있습니다. 물론 저처럼 두번째 문제가 있을때는 coredump 파일이 생성되지 않을 수도 있으니, 2번까지 확인해보세요.

한가지 더, ulimit으로 설정한 core dump size는 일시적입니다. 즉, reboot은 당연하고 세션이 끊어지면 초기화된다는 것이죠. 터미널 접속시 바로 설정되도록 적용하려면 아래와 같이 /etc/security/limites.conf 파일을 설정하시면 됩니다. 

# vi /etc/security/limits.conf

맨 아래에 아래와 같이 추가하여 저장하시면 반영구적으로 적용됩니다.

2. /proc/sys/kernel/core_pattern 편집하여 현재 디렉토리에 coredump 생성

원래 coredump 파일을 프로그램 실행 위치에 생성되는 것으로 알고 있는데, 저의 경우에는 그게 아니었습니다. 도대체 왜 나만 안되는거야 이러고 있을 때 google 형님께 여쭈어본 결과 /proc/sys/kernel/core_pattern에서 설정할수 있다고 하십니다. 이 파일이 coredump 파일을 어떻게 생성하는지 정의하고 있는데, 열어보면 어떤 이상한 경로로 되어있을 가능성이 있습니다. 저는 과감하게 바꿔줬습니다. 

# echo "core.%e.%p" > /proc/sys/kernel/core_pattern

%e와 %p는 format문자로 저도 모릅니다. google형님이 알려준대로 썼으니까요. 이제 바꿔주고 coredump되는 실행파일을 실행시켜주면 그 디렉토리에 coredump 파일이 뜨게 됩니다.

core 덤프 파일이름을 보면 %e는 프로그램 이름, %p는 pid인 듯 보이네요.

 

1. segfault 의미

- segmentation fault

- the application is trying to access a memory area that belongs to the OS or some other program. The memory management unit in the CPU stops the operation and triggers an exception. The standard segfault exception handler in the kernel kills the program.

- the program probably tried to use an uninitialized pointer, which has a value NULL

 

2. segfault 예

- scagent[1569]: segfault at 7f2ecca29fc8 ip 00000039ff64432a sp 00007f2ecca29fd0 error 6 in libc-2.12.so[39ff600000+18a000]

- epi_alert_svr[26620]: segfault at 0 ip 00000000004142db sp 00002af6e33efd20 error 4 in epi_alert_svr[400000+1c000]

 

3. segfault 원인

- 잘못된 메모리 공간에 쓰기 시도(허용되지 않은 메모리 영역에 접근을 시도, 허용되지 않은 방법으로 메모리 영역에 접근을 시도). 예를 들어, 읽기 전용 영역에 어떤 내용을 쓰려고 시도하거나, 운영 체제에서 사용하는 영역에 다른 내용을 덮어쓰려 하는 경우

- 메모리 문제

- 하드디스크에 배드 섹터가 있어도 발생

- 개발 소스 아키텍처 관련 문제

 

4. segfault 항목의 의미

- ip(rip): instruction pointer. ie. where the code which is trying to do this lives

- sp(rsp): stack pointer

- at: address. (it's likely that 10 and 11 are offsets from a pointer we expect to be set to a valid value but which is instead pointing to 0)

- error: value of page fault error code, ie. last error code which was reported by a syscall

- [39ff600000+18a000]: starting address and size of virtual memory area where offending object was mapped at the time of crash

 

5. segfault error 넘버의 의미

- 4: The cause was a user-mode read resulting in no page being found.(also known as a null pointer dereference)

     4 is EINTR (interrupted system call)

- 6: The cause was a user-mode write resulting in no page being found.

 

6. segfault 조치 방법

If possible, have your application developer produce a version of the application that includes debug information. If the application is compiled using gcc, this is as simple as adding the "-g" option to the compilation commands. 

 

Before starting the application, run "ulimit -c unlimited". This allows the segfault handler to produce a core dump file when the segfault handler is triggered. This file contains all the memory used by the application, so it might be very big.

 

Then your application developer needs to run a debugger program on the application and the core file. If the application was compiled with debug information, the debugger can identify exactly on what line of the source code the error happened. The developer can also use the debugger to examine the values of any variables at the time of the error. The debugger has many other features which might be useful too. If your developer does not know how to use a debugger, he/she should definitely learn it.

 

For Linux, the most common debugger program is named "gdb" and it is available in most Linux distributions. It is usually in the "development tools" category of the distribution's package collection.

 

7. 참조 URL

- http://rgeissert.blogspot.kr/2013/07/explaining-segmentation-fault-errors.html

- http://rgeissert.blogspot.kr/p/segmentation-fault-error.html

- http://stackoverflow.com/questions/2549214/interpreting-segfault-messages

- http://adnoctum.tistory.com/387

 

What is a segfault?

A segmentation fault (also known as a segfault or a segmentation violation) occurs when a process attempts to access a memory location that it is not allowed to access, or attempts to access a memory location in a way that is not allowed (for example, attempting to write to a read-only location, or to overwrite part of the operating system). On Unix family operating systems, a signal called SIGSEGV - signal #11, defined in the system header file signal.h - is then sent to to process. The default action for SIGSEGV is abnormal termination: the process ends and an application core file may be written (depending on the system's configuration).

On some architectures (notably x86_64), the kernel logs a message to the kernel ring buffer when a segfault is generated.


Why does a segfault occur?

A segmentation fault can occur under the following circumstances:
1. A bug (software defect) in the program or command is encountered, for example a buffer overflow (an attempt to access memory beyond the end of an array). This can typically be resolved by applying errata or vendor software updates.
2. A hardware problem affects the virtual memory subsystem. For example, a RAM DIMM or CPU cache is defective.
3. An attempt is made to execute a program that was not compiled/built correctly.

 

https://doitnow-man.tistory.com/102

[Segfault] Core가 없을때 dmesg로 죽은 원일 분석 하기

1. dmesg 정보로 정보 수집 

  - 코어가 남지 않았을 경우 모든 Core로그는 dmesg에 남는다.

  - 수행 명령어

#dmesg 

  - 추출 가능 정본는 다음과 같다.

 

 항목     정보  값 
 1   프로그램 명  segfault_test 이고 pid 는 959 이다.  
 2   죽은 원인  segmentfault가 발생하여 죽음 
 3   죽을 때 참조한 주소  잘못된 참조 주소 0 
 ( 0은 NULL 값을 참조 했음을 의미 한다)
 4   죽었을때 실행된 명령어 주소  죽었을 당시 실행된 명령어 0x400541
 5   죽었을때 스택 주소  죽었을 당시의 스택 주소  
 6   에러 코드  에러 코드  
 7    offset 정보  Offset 정보 

 

 2. dmesg의 정보를 활용하여 어떤 명령어를 수행 하다 죽었는지 확인 하는방법

  1) 실행 파일 전체를 disassemble화 시킨다. 

    - objdump를 사용하며, 이 Tool는 linux에 내장되어있는 tool 이다.

    - objdump 온셥 설명

      D :  Display assembler contents of all sections

 C :  Decode mangled/processed symbol names

 l(소문자 L)  : Include line numbers and filenames in output

    #objdump -DCl ./segfault_test_gdb > coreDump

 

  2) coreDump 파일 내용 보기 

    - 현재 coreDump 파일에는 disassemble 되어 있는 정보가 존재하기에 우리는 

      IP(Instruction Pointer) 주소를 알기에 해당 주소에 대한 disassemble 코드만 보면된다.

    - grep을 통하여 coeDump 내용을 확인한다. 

    - grep 옵션 설명

      n  : line 정보 표시 

      B  : 일치하는 정보 앞으로 몇 line을 보여줄것인가

      A  : 일치하는 정보 뒤로 몇 line을 보여줄것인가

      "40064a" : 찾을 문자열 

     ./coreDump : 검색 대상 

    #grep -n -B 20 -A 20 "40064a" ./coreDump    

  3) coreDump 내용 분석 (어떻게 죽었는지 유추를 하기위한 목적)

    1) 죽을 떄 실행된 코드 주소, 즉 IP(Instruction Pointer)는 0x40064a 이다

    2) 코드 정보 : movzbl (%rax), %eax

      - 어딘가에 값을 이동 하다 죽었다고 유추 할수 있다.

      - Assemble에 능숙한 사람이라면 코드를 좀더 잘 해석 할수 있을 것이다.

 

코어덤프 분석하기

core dump는 프로그램의 세그먼트 폴트 등의 비정상적인 종료가 발생하는 경우 커널에서 해당 프로세스와 관련된 메모리를 덤프시킨 파일이다. 해당 파일을 가지고 디버깅 하여 문제의 원인을 찾을 수 있다.

시스템 운영시 제일 많이 접하게 되는 JVM이 문제가 생기면 hs_err_pid.log라는 파일을 남기고 죽는데 이 파일을 보면 어느 작업을 하다가 죽었는지를 확인할 수 있다. 그러나 이 파일도 남기지 않는 경우도 있다.

리눅스에서는 gcore라는 명령어를 사용해서 코어덤프를 남길 수 있는다. 문제가 생겼을 때 (비 정상적으로 JVM이 죽었을 때 아무런 로그가 없는 경우 등)에는 이 코어 덤프가 유용한 분석자료가 될 수 있다. 

기본적으로 대부분의 서버에서는 코어 덤프를 남기지 않도록 되어 있다. java에서 1 GB 의 메모리를 사용하면 코어 덤프는 수십 기가에 달하는 파일을 생성하기 때문이다. 

이 때 JVM이 아무런 근거를 남기지 않고 죽었으면 둘 중 하나다.

누가 kill -9 pid로 프로세스를 죽었거나, segfault와 같이 프로세스 내의 오류로 죽는 경우다. 

이때 접속자와 수행한 명령어 등 로그를 확인해야한다.

/var/log/messages 

last

history (timestamp 기록되게 설정 필요)

1. 코어덤프 자동으로 생성하게 만들기

먼저 core dump를 자동으로 생성토록 하려면  ulimit -a 라는 명령으로 서버 설정을 확인한다. 

$ ulimit -a

core file size          (blocks, -c) 0

data seg size           (kbytes, -d) unlimited

scheduling priority             (-e) 0

file size               (blocks, -f) unlimited

pending signals                 (-i) 11589

max locked memory       (kbytes, -l) 64

max memory size         (kbytes, -m) unlimited

open files                      (-n) 1024

pipe size            (512 bytes, -p) 8

POSIX message queues     (bytes, -q) 819200

real-time priority              (-r) 0

stack size              (kbytes, -s) 10240

cpu time               (seconds, -t) unlimited

max user processes              (-u) 11589

virtual memory          (kbytes, -v) unlimited

file locks                      (-x) unlimited

이처럼 가장 끝에 있는 값이 0 이면 core dump 는 안남는다. 덤프를 남기도록 변경하려면, 0 그 이상의 숫자를 입력하거나 unlimited를 입력한다.

ulimit -c unlimited

확인

# ulimit -a

core file size          (blocks, -c) unlimited

# ulimit -c 1048576     // 1GByte로 제한

# ulimit -a

core file size          (blocks, -c) 1048576

명령을 실행하면 core dump가 남을 것이다. 단 디스크가 꽉 차버릴 수가 있으므로 조심해서 옵션을 변경해야만 한다.

unlimited로 변경한 콘솔 창에서 실행한 프로그램은 죽어버리면, 문제가 생기던 core dump 가 실행한 위치에서 남는다. 확인해 보려면 자바 프로그램 아무거나 작은거 하나 실행하고 

설정이 잘 되었다면, 'kill -11 pid'를 실행하여 core dump를 남길 수 있다.

위와 같은 설정은 리부팅을 하면 초기화되므로 아래와 같이 영구적 설정하도록 한다. (RHEL 6.x 환경)

방법 1

# vim /etc/profile  //맨 아래줄에 한 줄 추가한다.

ulimit -c unlimited > /dev/null 2>&1

방법 2

# vim /etc/security/limits.conf  // core가 명시된 1줄을 주석 제거, 수정

#<domain>      <type>  <item>         <value>

*                soft    core            -1     --> -1은 unlimited 이다.(기본은 0 임)

#*               hard    rss             10000

#@student        hard    nproc           20

#@faculty        soft    nproc           20

#@faculty        hard    nproc           50

#ftp             hard    nproc           0

#@student        -       maxlogins       4

2. file 명령으로 어느 파일의 core dump 인지 확인

예) file core.26325

core.26325: ELF 64-bit LSB core file x86-64, version 1 (SYSV), SVR4-style, from './frontend'

일단 프로세스가 비정상 종료 되었을때 실행파일이 존재하는 경로에 core 파일이 생성된다.

core파일명은 /proc/sys/kernel/core_pattern 에서 정의된 형태로 만들어진다.

디렉토리에 core.???? 형태의 파일이 생성되었다면 데몬이 크래쉬되고 재시작되었다고 판단하면 된다.

※ core dump 설정 확인

core와 관련된 커널 파라미터 설정은 다음과 같다.

# sysctl -a | grep core

kernel.core_pattern = core

kernel.core_uses_pid = 1

# cat /proc/sys/kernel/core_pattern

core

# cat /proc/sys/kernel/core_uses_pid

1  (0일 경우 pid를 출력하지 않음)

Tip. core 덤프가 발생할 때 프로세스 실행파일명으로 core 덤프를 떨어뜨리는 방법

1) sysctl -w kernel.core_pattern = core.%e  (reboot후 초기화 된다.)

2) echo "core.%e" > /proc/sys/kernel/core_pattern

3) /etc/sysctl.conf 파일에 아래 내용을 등록해 준다.

kernel.core_pattern = core.%e

core dump 파일 위치 및 이름 규칙 설정하기 

%p: pid

%: '%' is dropped

%%: output one '%'

%u: uid

%g: gid

%s: signal number

%t: UNIX time of dump

%h: hostname

%e: executable filename

%: both are dropped

3. 코어 덤프 수동으로 생성하는 방법

디버깅을 위해 특정 프로세스에 대해 강제로 core dump를 발생시켜야 하는 경우.

1) kill 커맨드를 이용할 수 있다.

# kill -l // 옵션 목록

 1) SIGHUP       2) SIGINT       3) SIGQUIT      4) SIGILL

 5) SIGTRAP      6) SIGABRT      7) SIGBUS       8) SIGFPE

 9) SIGKILL     10) SIGUSR1     11) SIGSEGV     12) SIGUSR2

13) SIGPIPE     14) SIGALRM     15) SIGTERM     17) SIGCHLD

18) SIGCONT     19) SIGSTOP     20) SIGTSTP     21) SIGTTIN

22) SIGTTOU     23) SIGURG      24) SIGXCPU     25) SIGXFSZ

26) SIGVTALRM   27) SIGPROF     28) SIGWINCH    29) SIGIO

30) SIGPWR      31) SIGSYS      34) SIGRTMIN    35) SIGRTMIN+1

36) SIGRTMIN+2  37) SIGRTMIN+3  38) SIGRTMIN+4  39) SIGRTMIN+5

40) SIGRTMIN+6  41) SIGRTMIN+7  42) SIGRTMIN+8  43) SIGRTMIN+9

44) SIGRTMIN+10 45) SIGRTMIN+11 46) SIGRTMIN+12 47) SIGRTMIN+13

48) SIGRTMIN+14 49) SIGRTMIN+15 50) SIGRTMAX-14 51) SIGRTMAX-13

52) SIGRTMAX-12 53) SIGRTMAX-11 54) SIGRTMAX-10 55) SIGRTMAX-9

56) SIGRTMAX-8  57) SIGRTMAX-7  58) SIGRTMAX-6  59) SIGRTMAX-5

60) SIGRTMAX-4  61) SIGRTMAX-3  62) SIGRTMAX-2  63) SIGRTMAX-1

64) SIGRTMAX

위의 시그널 중에서 8)SIGFPE 또는 3)SIGQUIT 를 통해 core를 dump시킬 수 있다.

터미널 두 개를 띄운다.

터미널 1)

# top (top 실행)

# ps -ef | grep -i top (top 프로세스 PID 확인, 다른 터미널에서)

root     31775 29667  0 14:30 pts/3    00:00:00 top

터미널 2)

# kill -SIGFPE 31775

위와 같이 하면 top을 실행한 디렉토리에 core.top.31775가 생성되어있음을 확인할 수 있다.

2) gcore를 이용한 core dump 발생

디버깅을 위해 현재 실행중인 프로세스를 강제로 core dump를 생성할 필요가 있는 경우 gcore를 이용할 수 있다.

터미널 1)

# top (top 실행)

# ps -ef | grep -i top (top 프로세스 PID 확인, 다른 터미널에서)

root     31775 29667  0 14:30 pts/3    00:00:00 top

터미널 2)

# gcore 31775

gcore: core.31775 dumped

참고 : gcore 바이너리는 gdb 패키지에 포함돼 있다. (gdb-6.3.0.0-1.143.el4.i386.rpm)

4. 코어덤프 저장위치

RHEL 6.x 은 core dump 파일을 abrtd와 abrt-ccpp 데몬에 의해 자동으로 수집, 저장한다.

참고

abrtd, abrt-cpp는 Fedora12, RHEL 6.x 부터 추가된 패키지로 커널 및 어플리케이션 크래쉬를 자동으로 감지하여 보고해 주는 도구이다. 따라서 core dump가 발생되길 원한다면 abrtd와 abrt-cpp 데몬은 실행되도록 한다.

또한 kernel.core_pattern 은 아래와 같이 설정이 되어 있다.

# sysctl -a | grep kernel.core_pattern

kernel.core_pattern = |/usr/libexec/abrt-hook-ccpp %s %c %p %u %g %t e

/etc/sysctl.conf 에서 kernel.core_pattern 의 저장 경로와 파라미터를 변경하려 하여도 abrtd, abrt-ccpp 데몬에 의해 자동으로 위와 같은 값으로 변경된다.

따라서 RHEL 6.x 전의 Legacy 방식으로 경로를 지정해 주기 위해서는 abrtd, abrt-ccpp 데몬을 올리지 않고서 지정해 주어야 한다.

1) 기본 위치

저장 위치는 /var/spool/abrt 이다.

2) 위치 변경

arbtd 및 arbt-cpp 데몬에 의해 /var/spool/abrt 디렉토리 내에 dump 파일이 떨어지게 되는데 위치 변경을 위해서는 아래와 같이 한다.

# abrt.conf 파일을 수정한다.

# vim /etc/abrt/abrt.conf

.

.

#DumpLocation = /var/spool/abrt  //기본 값이고, 주석처리되어 있다.

DumpLocation = /var/crash  // 원하는 경로를 넣는다.

abrtd 데몬 restart

# /etc/init.d/abrtd restart

 

Stopping abrt daemon:                                      [  OK  ]

Starting abrt daemon:                          

5. 코어덤프 분석하기

코어덤프 파일을 열기 위해서는 gdb라는 프로그램을 사용하면 된다. 자바 프로그램을 확인하려면,

gdb /자바실행파일FullPath/java core.pid

예) gdb ./frontend ./core.26325

로 실행하면 된다. 그러면 인터프리터 방식으로 이 툴을 사용할 수 있다.

명령어

backtrace(bt) : 죽기직전 호출되었던 호출스택 확인

break Abnomal : 마지막 호출 함수에 break point 설정, 그 이후 r 키로 한줄씩 디버깅

info thread

thread 쓰레드번호

where

x/i 메모리주소값

그런데, 코드가 완전 C로 되어 있다면 스텍 정보들이 제대로 나오겠지만, java로 되어 있으면 보기가 어렵다. (그냥 메소드 이름이 ??로 나온다.)

그럴때 사용하는게 바로 jstack이다.

6. jstack 으로 core dump의 쓰레드 덤프 생성하기

jstack으로 coredump의 쓰레드 덤프를 생성하는 방법은 다음과 같다.

jstack /자바실행파일FullPath/java core.pid

이렇게 실행하면 jstack이 코어덤프에서 쓰레드 덤프를 추출해준다. 마찬가지로 jmap 을 이용해서 core dump  에서 힙 덤프도 만들 수 있다.

출처 : http://cafe.naver.com/nexcore.cafe?iframe_url=/ArticleRead.nhn%3Farticleid=43

1.1.       Core Dump 파일 분석하기

1.1.1.   코어  덤프  파일  정보  보기 

 GDB로 코어 덤프 파일 분석하기 , gdb [프로그램명] [코어파일명]

 > gdb cursorserv core.9122

HP gdb 5.8 for HP Itanium (32 or 64 bit) and target HP-UX 11.2x.

Copyright 1986 - 2001 Free Software Foundation, Inc.

. . .

backtrace 명령어로 콜스택 backtrace

(gdb) bt

#0  inline std::allocator<char>::allocator(std::allocator<char> const&) ()

    at /opt/aCC/include_std/memory:252

#1  0x9fffffffbb8b7440:0 in inline std::basic_string<char,std::char_traits<char>,std::allocator<char> >::get_allocator() const ()

    at /opt/aCC/include_std/string:774

#2  0x9fffffffbb8b7420:0 in std::basic_string<char,std::char_traits<char>,std::allocator<char> >::basic_string (this=0x9fffffffffffdb58, __s=@0x0)

    at /opt/aCC/include_std/string:1035

#3  0x9fffffffbbbb2100:0 in nexcore::sql::Record::setValue (

    this=0x9fffffffffffdd30, key=@0x0, value=@0x9fffffffffffdca8)

    at nexcore/sql/Record.cpp:67

#4  0x9fffffffb99ec310:0 in int nexcore::sql::SqlManager::select<TestFun*,bool

    (this=0x600000000006d0c0, statementId=@0x9fffffffffffde00,

    params=0x9fffffffffffde30, c=0x60000000001340b0, mf=(bool ( class TestFun

    ::*)(class nexcore::sql::Record *...)) -147599808)

    at /home/jsh/nexbuild/nana/include/nexcore/sql/SqlManager.hpp:157

#5  0x9fffffffb99e9240:0 in TestFun::perform (this=0x60000000001340b0,

    request=0x6000000000141950, response=0x6000000000025840) at TestFun.cpp:103

#6  0x9fffffffbbc74510:2 in inline std::allocator<char>::allocator() ()

    at /opt/aCC/include_std/memory:250

의심되는 스택 프레임으로 이동한다. 예를 들어 4번 프레임을 조사하고 싶으면, frame 4를 입력한다.

 Frame 4를 선택해서 스택 정보 보기

(gdb) f 4

#4  0x9fffffffb99ec310:0 in int nexcore::sql::SqlManager::select<TestFun*,bool

    (this=0x600000000006d0c0, statementId=@0x9fffffffffffde00,

    params=0x9fffffffffffde30, c=0x60000000001340b0, mf=(bool ( class TestFun

    ::*)(class nexcore::sql::Record *...)) -147599808)

    at /home/jsh/nexbuild/nana/include/nexcore/sql/SqlManager.hpp:157

157                                                             record.setValue( colNames[i], rset->getString(i+1) );

 해당 스택의 소스 보기

(gdb) list

152                                             while(rset->next())

153                                             {

154                                                     Record record;

155                                                     for (int i=0; i<colCount; i++)

156                                                     {

157                                                             record.setValue( colNames[i], rset->getString(i+1) );

158                                                     }

159                                                    

160                                                     // call callback function

 해당 스택의 argument 보기

(gdb) info arg

this = (class nexcore::sql::SqlManager * const) 0x600000000006d0c0

statementId = (

    class std::basic_string<char, std::char_traits<char>, std::allocator<char>>

     &) @0x9fffffffffffde00: {_C_data = 0x600000000013a4f0 "select",

  static __nullref = <optimized out>, static npos = <optimized out>}

params = (class nexcore::sql::Params *) 0x9fffffffffffde30

c = (class TestFun *) 0x60000000001340b0

mf = (bool ( class TestFun::*)(class nexcore::sql::Record *...)) (bool (

    class TestFun::*)(class nexcore::sql::Record *...)) -147599808

 해당 스택의 local value 보기

(gdb) info local

i = 0

record = {record = {__t = {_C_buffer_list = 0x6000000000134d40,

      _C_free_list = 0x0, _C_next_avail = 0x60000000003cc650,

      _C_last = 0x60000000003ccc20, _C_header = 0x60000000003cc620,

      _C_node_count = 0, _C_insert_always = false,

      _C_key_compare = {<std::binary_function<std::string, std::string, bool>> = {<No data fields>}, <No data fields>}}}, __vfp = 0x9fffffffbb784110}

colCount = 2

resultCount = 0

selectCnt = 0

query = {

  _C_data = 0x6000000000033830 " SELECT A.NATION_CD AS nationCD, A.NATION_NM AS nationNM FROM PI_NATION A WHERE A.NATION_CD LIKE '%' || #nationCD# || '%' AND A.DEL_FLG='N' ", static __nullref = <optimized out>,

  static npos = <optimized out>}

위와 같은 방식으로 코어 덤프 파일로부터 콜스택을 추적하여 프로그램이 비정상 종료된 원인을 찾아낸다. 자세한 명령어 및 검사방법은 GDB 기본 명령어 참조한다.

추가 : local variable 이외에 해당 클래스의 멤버변수를 확인할 경우 print 또는 p를 사용한다.

(gdb) p 변수명   -> 일반 변수

(gdb) p* 변수명  -> 포인터형 변수(new등)

1.2.       실행중인 프로세스 디버깅

 실행중인 프로세스 PID 보기 , ps –ef | grep [프로세스 명]

 SKA1PAP1:/>ps -ef | grep ae001serv

muxplt1 28238     1  0 12:00:43 ?         0:00 ae001serv -g 1 -i 200 -u SKA1PAP1 -U  muxplt1  6153  6114  0 12:39:04 pts/10    0:00 grep ae001serv

 

 실행중인 프로세스에 attach , gdb [프로세스 명] [pid]

 SKA1PAP1:/ >gdb ae001serv 28238

HP gdb 5.8 for HP Itanium (32 or 64 bit) and target HP-UX 11.2x.

Copyright 1986 - 2001 Free Software Foundation, Inc.

. . .

현재 프로세스의 스택 정보

(gdb) where

#0  0x9fffffffe2e31ad0:0 in _msgrcv_sys+0x30 () from /lib/hpux64/libc.so.1

#1  0x9fffffffe2e41270:0 in msgrcv ()

    at ../../../../../core/libs/libc/shared_em_64_perf/../core/syscalls/t_msgrcv.c:19

#2  0x9fffffffe43ccfe0:0 in _tmmbrecvm () at msg/tmmbrecvm.c:364

#3  0x9fffffffe4195a10:0 in _tmmsgrcv () at tmgetrply.c:652

CoreDump란 무엇인가?

  • CoreDump1는 Linux 커널에서 문제가 발생했을 경우 발생했던 문제에 대한 정보를 찍어내는 정보 입니다.
  • CoreDump의 정보로 커널에 발생한 문제에 대해 분석이 가능하므로 시스템 엔지니어링에 대해 중요한 포인트라고 할 수 있을것 같습니다.
  • 그래서 저는 제가 공부를 한 개념을 토대로 CoreDump를 몇 가지 방법을 소개해 드리려고 합니다.

방법1. 명령어를 통한 일회성 CoreDump 생성

  1. ulimit -a 명령어를 통해 커널에 셋팅된 설정값들을 확인이 가능합니다, 저희는 core file size를 확인해야 합니다.
    아래 출력물을 보시면 core file size가 0으로 셋팅이 되어있는것을 보실 수 있는데요.
    이는 CoreDump 파일의 사이즈를 0으로 즉 찍지 않도록 설정이 되어있는것이지요.
    [root@JechBlog ~]# ulimit -a
    core file size          (blocks, -c) 0		## 이 부분!!
    data seg size           (kbytes, -d) unlimited
    scheduling priority             (-e) 0
    file size               (blocks, -f) unlimited
         ... 이하 생략 ...
    
  2. ulimit -c unlimited 명령어를 수행하면 아래와 같은 결과를 보실 수 있습니다.
    [root@JechBlog ~]# ulimit -c unlimited
    [root@JechBlog ~]# ulimit -a
    core file size          (blocks, -c) unlimited	## 이 부분!!
    data seg size           (kbytes, -d) unlimited
    scheduling priority             (-e) 0
    file size               (blocks, -f) unlimited
         ... 이하 생략 ...
    
    • 이 명령어는 커널의 core file size 셋팅값을 변경해주는 명령어 입니다.
    • 다만 이 명령어는 재부팅 후에는 다시 원복이 되기에 일회성이라고 보시면 될것같습니다.

방법2. 파일 수정을 통한 영구적 CoreDump 생성

  1. /etc/security/limits.conf 파일의 맨 마지막 하단에 라인을 추가 합니다.
    [root@JechBlog ~]# tail /etc/security/limits.conf
         ... 이하 생략 ...
    * soft nofile 65535
    * hard nofile 65535
    root soft nofile 65535
    root hard nofile 65535
    *       -       core    unlimited		## 이 부분!! (작성 필요)
    
    • 이 방법을 사용하여 설정했을 때는 재부팅 후에도 영구적으로 적용이 가능합니다.
    • 보통 고객사에 나가게 되면 영구적으로 설정이 필요하여 방법2의 방법이 많이 쓰이지 않을까 싶습니다.
320x100
반응형