1. 시그널 관련 코드 디버깅 및 분석
1. tlpi-dist/signals/ouch.c
1. 코드
#include <signal.h>
#include "tlpi_hdr.h"
static void
sigHandler(int sig)
{
printf("Ouch!\n");
}
int
main(int argc, char *argv[])
{
int j;
if (signal(SIGINT, sigHandler) == SIG_ERR)
errExit("signal");
for (j = 0; ; j++) {
printf("%d\n", j);
sleep(3);
}
}
2. 동작 모습

3. 디버깅 및 분석

- ctrl + c 로 시그널을 발생시키면 ^ouch 가 출력되는 코드인데 gdb에서 ctrl + c를 종료 시그널로 먹어서 디버깅 불가능
2. tlpi-dist/signals/t_kill.c
1. 코드
#include <signal.h>
#include "tlpi_hdr.h"
int
main(int argc, char *argv[])
{
int s, sig;
if (argc != 3 || strcmp(argv[1], "--help") == 0)
usageErr("%s pid sig-num\n", argv[0]);
sig = getInt(argv[2], 0, "sig-num");
s = kill(getLong(argv[1], 0, "pid"), sig);
if (sig != 0) {
if (s == -1)
errExit("kill");
} else {
if (s == 0) {
printf("Process exists and we can send it a signal\n");
} else {
if (errno == EPERM)
printf("Process exists, but we don't have "
"permission to send it a signal\n");
else if (errno == ESRCH)
printf("Process does not exist\n");
else
errExit("kill");
}
}
exit(EXIT_SUCCESS);
}
2. 동작 모습

3. 디버깅 및 분석

3. tlpi-dist/procexec/make_zombie.c
1. 코드
#include <signal.h>
#include <libgen.h>
#include "tlpi_hdr.h"
#define CMD_SIZE 200
int
main(int argc, char *argv[])
{
char cmd[CMD_SIZE];
pid_t childPid;
setbuf(stdout, NULL);
printf("Parent PID=%ld\n", (long) getpid());
switch (childPid = fork()) {
case -1:
errExit("fork");
case 0:
printf("Child (PID=%ld) exiting\n", (long) getpid());
_exit(EXIT_SUCCESS);
default:
sleep(3);
snprintf(cmd, CMD_SIZE, "ps | grep %s", basename(argv[0]));
system(cmd);
if (kill(childPid, SIGKILL) == -1)
errMsg("kill");
sleep(3);
printf("After sending SIGKILL to zombie (PID=%ld):\n", (long) childPid);
system(cmd);
exit(EXIT_SUCCESS);
}
}
2. 동작 모습

3. 디버깅 및 분석

4. tlpi-dist/procexec/multi_SIGCHLD.c
1. 코드
#include <signal.h>
#include <sys/wait.h>
#include "print_wait_status.h"
#include "curr_time.h"
#include "tlpi_hdr.h"
static volatile int numLiveChildren = 0;
static void
sigchldHandler(int sig)
{
int status, savedErrno;
pid_t childPid;
savedErrno = errno;
printf("%s handler: Caught SIGCHLD\n", currTime("%T"));
while ((childPid = waitpid(-1, &status, WNOHANG)) > 0) {
printf("%s handler: Reaped child %ld - ", currTime("%T"),
(long) childPid);
printWaitStatus(NULL, status);
numLiveChildren--;
}
if (childPid == -1 && errno != ECHILD)
errMsg("waitpid");
sleep(5);
printf("%s handler: returning\n", currTime("%T"));
errno = savedErrno;
}
int
main(int argc, char *argv[])
{
int j, sigCnt;
sigset_t blockMask, emptyMask;
struct sigaction sa;
if (argc < 2 || strcmp(argv[1], "--help") == 0)
usageErr("%s child-sleep-time...\n", argv[0]);
setbuf(stdout, NULL);
sigCnt = 0;
numLiveChildren = argc - 1;
sigemptyset(&sa.sa_mask);
sa.sa_flags = 0;
sa.sa_handler = sigchldHandler;
if (sigaction(SIGCHLD, &sa, NULL) == -1)
errExit("sigaction");
sigemptyset(&blockMask);
sigaddset(&blockMask, SIGCHLD);
if (sigprocmask(SIG_SETMASK, &blockMask, NULL) == -1)
errExit("sigprocmask");
for (j = 1; j < argc; j++) {
switch (fork()) {
case -1:
errExit("fork");
case 0:
sleep(getInt(argv[j], GN_NONNEG, "child-sleep-time"));
printf("%s Child %d (PID=%ld) exiting\n", currTime("%T"),
j, (long) getpid());
_exit(EXIT_SUCCESS);
default:
break;
}
}
sigemptyset(&emptyMask);
while (numLiveChildren > 0) {
if (sigsuspend(&emptyMask) == -1 && errno != EINTR)
errExit("sigsuspend");
sigCnt++;
}
printf("%s All %d children have terminated; SIGCHLD was caught "
"%d times\n", currTime("%T"), argc - 1, sigCnt);
exit(EXIT_SUCCESS);
}
2. 동작 모습

3. 디버깅 및 분석

2. 토이 프로젝트

2. main process 자식 프로세스 시그널 출력

3. 동작 모습
