23.11.19 최초 작성
/ui/input.c
: 콜 스택을 출력하는 segfault_handler
함수를 추가해 segment fault
가 발생할 경우 해당 함수를 작동시킴/main.c
: child process (system_server, gui, input, web_server)
의 중단을 알리는 함수 sigcldHandler
를 추가해 자식 프로세스의 종료를 확인함/main.c
: main()
에 시그널을 등록하는 코드 signal(SIGCHLD, sigcldHandler)
를 추가해 자식 프로세스의 종료를 확인함#include <stdio.h>
#include <sys/wait.h>
#include <signal.h>
#include <system_server.h>
#include <gui.h>
#include <input.h>
#include <web_server.h>
#include <asm-generic/signal-defs.h>
/// sigcldHandler
static void sigcldHandler(int sig){
printf("Received signal from child : %d\n", sig);
}
int main()
{
pid_t spid, gpid, ipid, wpid;
int status, savedErrno;
/// sigcldHandler assign
signal(SIGCHLD, sigcldHandler);
printf("메인 함수입니다.\n");
printf("시스템 서버를 생성합니다.\n");
spid = create_system_server();
printf("웹 서버를 생성합니다.\n");
wpid = create_web_server();
printf("입력 프로세스를 생성합니다.\n");
ipid = create_input();
printf("GUI를 생성합니다.\n");
gpid = create_gui();
waitpid(spid, &status, 0);
waitpid(gpid, &status, 0);
waitpid(ipid, &status, 0);
waitpid(wpid, &status, 0);
return 0;
}
/ui/input.c
: input()
함수에 sigaction()
코드를 작성해 SIGSEGV (segment fault)
가 프로세스에 전달되면 콜 스택을 출력하는 함수 segfault_handler()
가 작동하도록 함#include <stdio.h>
#include <sys/prctl.h>
#include <execinfo.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ucontext.h>
#include <unistd.h>
#include <system_server.h>
#include <gui.h>
#include <input.h>
#include <web_server.h>
#include <bits/sigaction.h>
typedef struct _sig_ucontext {
unsigned long uc_flags;
struct ucontext *uc_link;
stack_t uc_stack;
struct sigcontext uc_mcontext;
sigset_t uc_sigmask;
} sig_ucontext_t;
/// call stack print
void segfault_handler(int sig_num, siginfo_t * info, void * ucontext) {
void * array[50];
void * caller_address;
char ** messages;
int size, i;
sig_ucontext_t * uc;
uc = (sig_ucontext_t *) ucontext;
/* Get the address at the time the signal was raised */
caller_address = (void *) uc->uc_mcontext.rip; // RIP: x86_64 specific arm_pc: ARM
fprintf(stderr, "\n");
if (sig_num == SIGSEGV)
printf("signal %d (%s), address is %p from %p\n", sig_num, strsignal(sig_num), info->si_addr,
(void *) caller_address);
else
printf("signal %d (%s)\n", sig_num, strsignal(sig_num));
size = backtrace(array, 50);
/* overwrite sigaction with caller's address */
array[1] = caller_address;
messages = backtrace_symbols(array, size);
/* skip first stack frame (points here) */
for (i = 1; i < size && messages != NULL; ++i) {
printf("[bt]: (%d) %s\n", i, messages[i]);
}
free(messages);
exit(EXIT_FAILURE);
}
int input()
{
printf("Enter input process\n");
///segfault_handler 등록
struct sigaction siga;
siga.sa_sigaction = segfault_handler;
sigaction(SIGSEGV, &siga, NULL);
while (1) {
sleep(1);
}
return 0;
}
int create_input()
{
pid_t systemPid;
const char *name = "input";
printf("Creating input process\n");
switch(systemPid = fork()){
case -1:
perror("input process create failed \n");
case 0 :
if (prctl(PR_SET_NAME, (unsigned long) name) < 0)
perror("prctl()");
input();
break;
default :
break;
}
return 0;
}