Why the child process will not exit normally? - c

Why is the following program will not work properly?
int cnt = 0;
void deal(int sig) {
++cnt;
}
int main() {
signal(SIGUSR1, deal);
pid_t child = fork();
if (child == 0) {
ptrace(PTRACE_TRACEME, 0, NULL, NULL);
raise(SIGSTOP);
freopen("ab.out", "w", stdout);
printf("child : %d\n", cnt);
} else {
int app_status, app_sig, fd;
struct user_regs_struct app_reg;
struct rusage app_ruse;
waitpid(child, &app_status, 0);
printf("father: waitpid: %d\n", app_status);
while (1) {
ptrace(PTRACE_SYSCALL, child, NULL, NULL);
wait4(child, &app_status, 0, &app_ruse);
if (WIFEXITED(app_status)) {
printf("father: child exit normally, pid - %d\n", child);
break;
}
if (WIFSIGNALED(app_status) || (WIFSTOPPED(app_status)
&& WSTOPSIG(app_status) != SIGTRAP)) {
....
break;
}
ptrace(PTRACE_GETREGS, child, NULL, &app_reg);
if (app_reg.orig_rax == SYS_open && (fd = app_reg.rax) >= 0) {
kill(child, SIGUSR1);
}
}
}
return 0;
}
When run the program, got follow result
Why did the child process exit directly after receiving the signal?
The full code can got here.
https://pastebin.ubuntu.com/p/FddVZpfGH7/

Related

why child can't send signal to parent

parent:
volatile int signalval = 0;
void signal_handle_c(int sig_num)
{
printf("child SIGUSR1 ok\n");
signalval = 1;
};
int main(int argc,char**argv){
struct sigaction act, oldact;
act.sa_handler = signal_handle_c;
act.sa_flags = SA_NOMASK;//SA_ONESHOT |
pid_t pid=fork();
if (pid < 0)
printf("error in fork!");
else if (pid == 0) {
printf("exec child!%s\n",argv[1]);
int res = execl(argv[1], "testc", NULL);
printf("res=%d", res);
}
else {
sleep(3);
sigaction(SIGUSR1, &act, &oldact);
printf("now parent\n");
}
waitpid(pid,NULL,0);
return 0;
}
child:
volatile int signal_pipe_end = 0;
void signal_handle_c(int sig_num)
{
printf("child IGUSR1 ok\n");
signal_pipe_end = 1;
};
int main(int argc, char *argv[])
{
printf("now child run!");
while (1)
{
printf("now child send siganl\n");
kill(getpid(), SIGUSR1);
sleep(1);
}
}
parent try to receive the SIGUSR1 signal from child.but none!
run result:
exec child!./testc
now child run!now child
now parent
i hope can printf "child SIGUSR1 ok".
why child "kill" send signal fail.

Changing directories in a shell. Writing my own shell in C

I am writing a simple shell in C. Right now when I run the command cd only work in the current environment that I am. So for example if I am in the Desktop folder I can only cd for a folder inside Desktop, I can't go to other folders in my computer.
How do I control this change of directories?
Thant's my cd function right now. Please let me know if you need more information.
int cmd_cd(char **args)
{
if (args[1] == NULL) {
fprintf(stderr, "expected argument to \"cd\"\n");
} else {
if (chdir(args[1]) != 0) {
fprintf(stderr, args[1],strerror(errno));;
}
}
return 1;
}
Here is my exec function that calls cd
char* builtCommandList[] = {"cd", "exit"};
int builtinSize = sizeof(builtCommandList) / sizeof(char *);
int (*builtin_func[]) (char **) = {
&cmd_cd,
&cmd_exit
};
int execute(char **args){
if(args[0] == NULL)
return 1;
for(int i =0; i<builtinSize;i++){
if (strcmp(args[0], builtCommandList[i]) == 0) {
printf("function is here");
return (*builtin_func[i])(args);
}
}
pid_t pid, wpid;
int status;
pid = fork();
if (pid == 0) {
// Child process
if (execvp(args[0], args) == -1) {
fprintf(stderr, "error in child process");
}
exit(EXIT_FAILURE);
} else if (pid < 0) {
// Error forking
fprintf(stderr, "error forking");
} else {
// Parent process
do {
wpid = waitpid(pid, &status, WUNTRACED);
} while (!WIFEXITED(status) && !WIFSIGNALED(status));
}
return 1;
}

Why can't I catch SIGCHLD every time after fork?

I am trying to create 4 child processes and until the children die, parent should wait. I wrote a program but when I run this code, 1 out of 10, it can't catch the SIGCHLD from every child and my program goes to infinite loop after. It happens really rare but still..
Could you tell me why and how can I fix it?
Here is my code.
sig_atomic_t child_exit_status;
sig_atomic_t child_numbers = 0;
void clean_up(int signal_number, siginfo_t * info, void* context)
{
//printf("SIGCHILD from %d calling\n", info->si_pid);
waitpid(info->si_pid, &child_exit_status, 0);
child_numbers++;
}
int main(int argc, char **argv)
{
// SIGCHLD catcher
struct sigaction sigchld_action;
memset(&sigchld_action, 0, sizeof(sigchld_action));
sigchld_action.sa_sigaction = &clean_up;
sigchld_action.sa_flags = SA_SIGINFO;
sigaction(SIGCHLD, &sigchld_action, NULL);
int pid1, pid2, pid3, pid4;
printf("pid : %d\n", getpid());
pid1 = fork();
//child1
if(pid1 == 0)
{
printf("child1 %d, parent %d\n", getpid(), getppid());
}
else
{
pid2 = fork();
//child2
if(pid2 == 0)
{
printf("child2 %d, parent %d\n", getpid(), getppid());
}
else
{
pid3 = fork();
//child3
if(pid3 == 0)
{
printf("child3 %d, parent %d\n", getpid(), getppid());
}
else
{
pid4 = fork();
//child4
if(pid4 == 0)
{
printf("child4 %d, parent %d\n", getpid(), getppid());
}
else
{
while(child_numbers < 4)
{
}
printf("i got the signals.");
}
}
}
}
return 0;
}
I tried something new but it also doesn't work..
void clean_up(int signal_number, siginfo_t * info, void* context)
{
printf("SIGCHILD from %d calling\n", info->si_pid);
while (1)
{
int status;
pid_t pid = waitpid(-1, &status, WNOHANG);
if (pid <= 0)
{
break;
}
else
{
waitpid(pid, &status, 0);
break;
}
}
child_numbers++;
}

Creating shared memory in C

I created following method in C to create a shared memory segment to store counter value. But I can't store data in this segment.When I try to print the value of the counter it gives me a garbage value.Whats wrong with this code?
CreateCounter()
{
key = ftok(".",'B');
shmCntid = shmget(key,COUNTER_SIZE,IPC_CREAT|0666);
if(shmCntid == -1 )
{
perror("shmget");
exit(1);
}
else
{
printf("Creating new Sahred memory sement\n");
cntPtr = shmat(shmCntid,0,0);
if(cntPtr == -1 )
{
perror("shmat");
exit(1);
}
}
}
This method is called inside the main method as follows.
int *cntPtr;
int rowCnt;
sem_t s;
sem_t c;
sem_t r;
int main(int argc, int *argv[])
{
int pid, pid2, pid3, i;
CreateBuf1();
CreateBuf2();
CreateCounter();
GetInput(argv[1],*buf1Ptr);
sem_init(&c, 0, 1);
sem_init(&r, 0, 1);
sem_init(&s, 0, 1);
for( i = 0 ; i < 9; i++)
{
pid = fork();
if(pid < 0)
{
printf("Fork error !\n");
}
else if (pid == 0)
break;
}
if(pid < 0)
{
printf("Fork error !\n");
}
else if (pid == 0)
{
sem_wait(&r);
Grp1 (i,i);
cntPtr+=rowCnt;
sleep(1);
sem_post(&r);
sem_post(&c);
exit(0);
}
else
{
wait(NULL);
}
pid2 = fork();
if(pid2 < 0)
{
printf("Fork error !\n");
}
else if (pid2 == 0)
{
sem_wait(&c);
Grp2(9);
cntPtr+=colCnt;
sleep(1);
sem_post(&c);
exit(0);
}
else
{
wait(NULL);
}
// This space is to print the values..............
shmctl(shmBuf1id,IPC_RMID,0);
shmctl(shmBuf2id,IPC_RMID,0);
shmctl(shmCntid,IPC_RMID,0);
return 0;
}

Linux Shell Pipeline Execution

I am trying to implement a basic linux shell with support for pipelining. However, my code seems to hang or just not execute programs and I can't figure out why.
if (list_empty(&job_list))
job_index = 1;
bool dopipe = false;
if (list_size(&pipeline->commands) > 1)
dopipe = true;
esh_signal_sethandler(SIGCHLD, signal_handler);
esh_signal_block(SIGCHLD);
setpgid(0, 0);
pipeline->pgrp = getpgid(0);
pipeline->jid = job_index++;
list_push_back(&job_list, &pipeline->elem);
bool background = pipeline->bg_job;
pid_t pid;
if ( (pid = fork()) == 0)
{
//Child
if (pipeline->bg_job)
setpgid(0, 0);
int oldpipe[2];
int newpipe[2];
int count = 0;
int size = list_size(&pipeline->commands);
struct list_elem * current_job;
printf("SIZE: %zu\n", list_size(&pipeline->commands));
for (current_job = list_begin(&pipeline->commands); current_job != list_tail(&pipeline->commands); current_job = list_next(current_job))
{
if (count < size)
pipe(newpipe);
pid_t fpid = fork();
printf("fpid: %d\n", (int)fpid);
if (fpid == 0)
{
//Child
printf("Executing Child\n");
if (count > 0)
{
//prev command exists
dup2(oldpipe[0], 0);
close(oldpipe[0]);
close(oldpipe[1]);
}
if (count < size - 1)
{
//next command exists
close(newpipe[0]);
dup2(newpipe[1], 1);
close(newpipe[1]);
}
esh_command* cmd = list_entry(current_job, struct esh_command, elem);
printf("Running: %s %s\n", cmd->argv[0], cmd->argv[1]);
if (execvp(cmd->argv[0], cmd->argv) < 0)
esh_sys_fatal_error("Program Does Not Exist\n");
}
else
{
//Parent
//*
int status = 0;
if (waitpid(fpid, &status, 0) < 0)
esh_sys_fatal_error("Could not fork pipe\n");
//*/
printf("Parent\n");
if (count > 0)
{
//prev command exists
close(oldpipe[0]);
close(oldpipe[1]);
}
if (count < size - 1)
{
//next command exists
oldpipe[0] = newpipe[0];
oldpipe[1] = newpipe[1];
}
printf("End of Parent\n");
}
count++;
}
if (size > 1)
{
close(oldpipe[0]);
close(oldpipe[1]);
}
printf("Finished Pipeline\n");
exit(3);
}
else
{
//*
int status = 0;
commands->pid = pid;
//Parent
if (!background)
{
pipeline->status = FOREGROUND;
if (waitpid(pid, &status, 0) < 0)
printf("waitpid ERROR\n");
list_remove(&pipeline->elem);
}
else
pipeline->status = BACKGROUND;
//*/
}
esh_signal_unblock(SIGCHLD);
I am fairly certain the error has to do with either the piping, or the forking of child processes in the loop.

Resources