C child process runs its code twice - c

Total C noob here, looking for some help with fork(). I'm not sure why its print the child process 2 code twice. I believe it has to do with the sleep call because it was working fine before.
Output
Child Process 2
Process ID: 31973
Parent Process ID: 1
Child Process 1
Process ID: 31972
Parent Process ID: 1
Child Process 2
Process ID: 31974
Parent Process ID: 1
C Code
#define _XOPEN_SOURCE // required for cuserid to work
// includes
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/resource.h>
#include <time.h>
int main(void) {
getP0Info();
putenv("WHALE=7");
forkProcesses();
return 0;
}
// Prints an error message and exits if one occurs. Else, returns the system call value.
int print_if_err(int syscall_val, const char* syscall_name) {
if (syscall_val < 0) {
perror(syscall_name);
exit(errno);
} else {
//No syscall error; we can return
return syscall_val;
}
}
void forkProcesses() {
pid_t child1_pid = print_if_err(fork(), "fork");
if (child1_pid == 0) {
printf("\nChild Process 1\n");
printf("Process ID: %d\n", getpid());
printf("Parent Process ID: %d\n", getppid());
sleep(1);
int whale = atoi(getenv("WHALE"));
printf("C1: %d\n", whale);
}
pid_t child2_pid = print_if_err(fork(), "fork");
if (child2_pid == 0) {
printf("\nChild Process 2\n");
printf("Process ID: %d\n", getpid());
printf("Parent Process ID: %d\n", getppid());
}
}

That's because child process 1's execution continues even after the if-statement is over. You need to explicitly do a return or call _exit() or such to prevent this:
void forkProcesses() {
pid_t child1_pid = print_if_err(fork(), "fork");
if (child1_pid == 0) {
printf("\nChild Process 1\n");
printf("Process ID: %d\n", getpid());
printf("Parent Process ID: %d\n", getppid());
sleep(1);
int whale = atoi(getenv("WHALE"));
printf("C1: %d\n", whale);
_exit(0);
}
pid_t child2_pid = print_if_err(fork(), "fork");
if (child2_pid == 0) {
printf("\nChild Process 2\n");
printf("Process ID: %d\n", getpid());
printf("Parent Process ID: %d\n", getppid());
}
}

Related

How do find the granchild pid in C?

I am trying to code a toy process manager and was wondering how do I find the grandchild pids when one of my children pids dies. I.e. how to deal with the "Readiness protocol".
systemd has the "Type=forking" option, which as far as I understand, waits for the forked pid to die and then assumes that one of the forked pid's children is the actual "daemon" to monitor.
My code so far is as following, but I am missing the XXX
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/prctl.h>
int
main (int argc, const char *argv[])
{
printf("sup stared\n");
int pid;
prctl(PR_SET_CHILD_SUBREAPER);
pid = fork();
if (pid == 0) {
setpgid(0, 0);
printf("service started, pid: %d, pgid: %d\n",
getpid(), getpgid(0));
int dpid;
dpid = fork();
if (dpid == 0) {
printf("daemon started, pid: %d, pgid: %d\n",
getpid(), getpgid(0));
while (1);
}
printf("service exiting\n");
return 0;
} else {
printf("service pid: %d\n", pid);
int rc;
rc = waitpid(pid, NULL, 0);
printf("service exited? %d\n", rc);
int dpid;
dpid = XXcX();
printf("daemon, %d\n", dpid);
}
return 0;
}

How would you change the code so that the child and parent run concurrently?

I am struggling to understand this question. Aren't the child and parent already running concurrently? Would the answer be to remove wait(NULL)? Please help.
Here the Code:
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
int main (int args, char *argv[])
{
pid_t fork_return;
pid_t pid;
pid=getpid();
fork_return = fork();
if (fork_return==-1) {
// When fork() returns -1, an error has happened.
printf("\nError creating process " );
return 0;
}
if (fork_return==0) {
// When fork() returns 0, we are in the child process.
printf("\n\nThe values are Child ID = %d, Parent ID=%d\n", getpid(), getppid());
execl("/bin/cat", "cat", "-b", "-v", "-t", argv[1], NULL);
}
else {
// When fork() returns a positive number, we are in the parent process
// and the return value is the PID of the newly created child process.
wait(NULL);
printf("\nChild Completes " );
printf("\nIn the Parent Process\n");
printf("Child Id = %d, Parent ID = %d\n", getpid(), getppid());
}
return 0;
}

how can I send a signal between a child and a parent processes in linux

I have two cods the first one is for the parent which sends a signal (SIGUSER1) to the child and when the child receive it he should print that he received it.
Parent code
#include <stdio.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <unistd.h>
#include <sys/types.h>
void sighand(int);
int main()
{
int cpid, ppid;
ppid = getpid();
printf("My process ID is %d\n", ppid);
FILE *fp1;
fp1 = fopen("cpid.txt", "w+");
cpid = fork();
if ( cpid == 0 ) {
printf("I am the child => PID = %d\n", getpid());
}
else
printf("I am the parent => PID = %d, child ID = %d\n", getpid(), cpid);
fprintf(fp1, "%d\n", cpid);
// kill(cpid, SIGUSR1);//id, signal, send
sigset(SIGUSR2, sighand);
return 0;
}
void sighand(int the_sig){
if (the_sig == SIGUSR2){
printf("sigusr2 received");
exit(1);
}
}
Child code
#include <stdio.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <unistd.h>
#include <sys/types.h>
void sighand1(int);
int main()
{
FILE *fp1;
int pid;
fp1 = fopen("cpid.txt", "r");
fscanf(fp1, "%d,", &pid);
sigset(SIGUSR1,sighand1);
while(1) {
printf("Waiting..");
sigpause(SIGUSR1);
}
return 0;
}
void sighand1(int the_sig)
{
if (the_sig == SIGUSR1){
printf("sigusr1 received");
exit(1);
}
}
When I start the code it prints that the process (child) was created then when I send a signal it wont do any thing the child stuck in a loop or the wait and the parent wont do anything can any one tell me where did i go wrong in my code or logic.
Your code has several problems:
You try to pass some pid through a file, but you can use the getppid() function (get parent id)
You have some child code, but it is not called
no signal is launched
So your code can be corrected this way:
#include <stdio.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <unistd.h>
#include <sys/types.h>
#include <signal.h>
void parent_handler(int the_sig)
{
if (the_sig == SIGUSR2){
printf("sigusr2 received in parent\n");
}
}
void child_handler(int the_sig)
{
if (the_sig == SIGUSR1){
printf("sigusr1 received in child\n");
kill(getppid(), SIGUSR2);
exit(1);
}
}
int child_function()
{
/* prepare to receive signal */
sigset(SIGUSR1,child_handler);
while(1) {
printf("Waiting..");
fflush(stdout);
/* wait for signal */
sigpause(SIGUSR1);
}
return 0;
}
int main()
{
int cpid, ppid;
ppid = getpid();
printf("My process ID is %d\n", ppid);
cpid = fork();
if ( cpid == 0 ) {
printf("I am the child => PID = %d\n", getpid());
child_function();
return 0;
}
else
printf("I am the parent => PID = %d, child ID = %d\n", getpid(), cpid);
/* child will never reach this point */
sleep(1);
/* prepare parent to received signal */
sigset(SIGUSR2, parent_handler);
/* send signal to child */
kill(cpid, SIGUSR1);
sleep(1);
return 0;
}

Set fork()'s child into foreground, and exit parent

I am trying to change the PID of a process in Linux.
Then the idea is to use fork() to spawn a child, and give the control of the terminal to this child, then exit from parent.
The result would be a new process with new process PID without interrupting the execution flow.
I've coded the following PoC, but it doesn't work. If I don't use wait() on the parent, the child process doesn't take control of the terminal. I mean, it continues outputting but the stdin is not attached to the child, is owned by bash.
#include <string.h>
#include <stdio.h>
#include <asm/ptrace.h>
#include <unistd.h>
#include <sys/syscall.h>
#include <linux/sched.h>
#include <stdlib.h>
#include <signal.h>
int main(void) {
int i = 0, ret = 0;
pid_t pid = 0;
printf("PID = %d\n", getpid());
pid = fork();
if (pid == -1) {
return -1;
}
if (pid != 0) {
printf("Parent PGID = %d\n", getpgid(0));
printf("Parent PGID for 0 = %d\n", tcgetpgrp(0));
signal(SIGTTOU, SIG_IGN);
for (i = 0; i < 3; i++) {
ret = tcsetpgrp(i, pid);
}
exit(0);
}
setpgid(0, 0);
printf("Child PGID = %d\n", getpgid(0));
printf("Child PGID for 0 = %d\n", tcgetpgrp(0));
for (i = 0; 1; i++) {
printf("iter = %d, PID = %d\n", i, getpid());
usleep(300000);
}
return 0;
}
Thanks in advance.

child-process signal handling in c

I need your help in an exercise i have about signal handling between processes. I think that it's a trivial question but i can't find the answer anywhere. I want to print something from the parent in a file, send a signal from the parent to the child, the child has to print in a file and then send a signal from the child to the parent.
The code i am using is this:
#include <stdio.h>
#include <sys/types.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <signal.h>
#include <unistd.h>
#define WRITEF 123451 //Random number
FILE *infile;
void writef() {
fprintf(infile, "Child Starting (%d)\n", getpid());
printf("Child Starting (%d)\n", getpid());
}
int main() {
pid_t pid;
infile = fopen("pid_log.txt","w");
pid = fork();
signal(WRITEF, writef);
if ( pid == 0 ) {
pause();
printf("enter child\n");
}
else {
fprintf(infile, "Parent (%d)\n", getpid());
printf("Parent (%d)\n", getpid());
kill(pid, WRITEF);
pause();
wait((int*)1);
}
fclose(infile);
return 1;
}
PROBLEM SOLVED!!!
The key is that you have to register the signal (use the singal function) before every pause(). Also you cannot use a "user-made" signal and in my case i used SIGCONT.
Here is the final (almost) version of my program:
#include <stdio.h>
#include <sys/types.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <signal.h>
#include <unistd.h>
FILE *infile;
void noth() {
}
void writec() {
infile = fopen("pid_log.txt","a+");
fprintf(infile, "Child (%d)\n", getpid());
printf("Child (%d)\n", getpid());
fclose(infile);
}
void writep() {
infile = fopen("pid_log.txt","a+");
fprintf(infile, "Parent (%d)\n", getpid());
printf("Parent (%d)\n", getpid());
fclose(infile);
}
main() {
pid_t pid = fork();
if ( pid == 0 ) { //child process
signal(SIGCONT,noth); //registering signal before pause()
pause();
infile = fopen("pid_log.txt","a+");
printf("Child Starting (%d)\n",getpid());
fprintf(infile,"Child Starting (%d)\n",getpid());
fclose(infile);
while (1) {
sleep(2);
kill(getppid(), SIGCONT); //sending singal to parent
signal(SIGCONT, writec);
pause();
}
}
else { //parent process
infile = fopen("pid_log.txt","a+");
printf("Parent Starting (%d)\n",getpid());
fprintf(infile,"Parent Starting (%d)\n",getpid());
fclose(infile);
kill(pid, SIGCONT);
signal(SIGCONT, writep);
pause();
while (1) {
sleep(2);
kill(pid, SIGCONT);
signal(SIGCONT, writep);
pause();
}
}
return 1;
}

Resources