How to detach a forked process from parent in C - c

So i am designing a basic UNIX shell in C.
signal(SIGCHLD, handler);
pid = fork();
switch (pid) {
case -1: printf("Fork failed; cpid == -1\n");
break;
case 0: child_pid = getpid();
argv[0] = prog;
argv[1] =NULL;
//exit(0);
sid = setsid();
execv(absPath,argv);
//printf("%d: this is the child, pid = %d\n", i, child_pid);
//sleep(1);
//exit(0);
break;
default: printf("This is the parent: waiting for %d to finish\n", pid);
waitpid(pid, NULL, WNOHANG);
printf("Ttttthat's all, folks\n");
//break;
}
//execv(absPath,argv);
//printf("CHILD PROCESS");
}
}
void handler(int sig)
{
pid_t pid;
pid = wait(NULL);
printf("Pid %d exit.\n", pid);
exit(0);
}
But it still executes the forked process in the same shell, though after the "default" clause.
Can you please help me make it run as a background process? Thanks!
P.S: This is just a snippet.

Commenting on some obvious errors:
In the child process you execute exit(0); thus exiting the child process immediately. Remove this line.
I think that for clarity you should call execv() like this execv(argv[0], argv);
Edit:
Read the following to solve the problem with forking from a child process.

As part of my Fat Controller application, I made a lib that will daemonise a process. Download the source and take a look at daemonise.c - it should be relatively well commented but if you have any further questions then I'd be glad to help.
http://sourceforge.net/projects/fat-controller/files/

Related

c fork's child ppid does not match parent's pid

I'm totally new to C.
I tried the following code, expecting that the child's ppid would match the parent's pid, but this is not the case.
int main() {
int pid;
printf("I'm process with pid=%d\n", getpid());
switch (pid = fork()) {
case -1:
perror("fork");
exit(1);
case 0:
printf("I'm the child process: pid=%d, ppid=%d\n", getpid(), getppid());
break;
default:
printf("I'm the parent process: pid=%d, ppid=%d\n", getpid(), getppid());
break;
}
exit(0);
}
> gcc -o fork fork.c
> ./fork
I'm process with pid=16907
I'm the parent process: pid=16907, ppid=6604
I'm the child process: pid=16908, ppid=1 // <-- expected ppid=16907, why 1?
>
What did I do wrong ?
It is likely the parent process has already exited and no longer exists. You could try some delay in the parent.
'init' which is the root process running in a linux system has pid 1 .
When a process's parent gets terminated before itself(i.e. the child) , the child becomes an 'orphan' process and is taken up by the root process or the process just above the hierarchy of the process which created it(parent process) .
Hence , here it is taken up by and executed under init which has pid = 1 .
So, delay your parent process for solution.
Like others have mentioned, looks like the parent process has terminated while the child process is still under execution making it(the child process) an orphan. Adding delay before exiting may work.
But an elegant way of doing it is, the parent process has to wait till the child process terminates.
This can be achieved by calling waitpid() with the pid of the child (the value returned by fork() ). When the control comes out of this function, you can be sure that the child process has terminated. Also, waitpid() returns the status of the process termination. Based on the status that it returns, you can get to know the normal/abnormal child termination.
Here is the code that does it:
int main() {
int pid;
int status = 0;
printf("I'm process with pid=%d\n", getpid());
switch (pid = fork()) {
case -1:
perror("fork");
exit(1);
case 0:
printf("I'm the child process: pid=%d, ppid=%d\n", getpid(), getppid());
break;
default:
waitpid(pid, &status, 0);
if(WIFEXITED(status)
{
printf("Normal termination of child process %d\n", pid);
}
else
{
printf("Abormal termination of child process %d\n", pid);
}
printf("I'm the parent process: pid=%d, ppid=%d\n", getpid(), getppid());
break;
}
exit(0);
}

Why are my child background process (fork-execvp) die instatly, but work well while in the foreground?

I'm doing a homework assigment (the regular "write your own unix shell in c" assigment)
and cant make my child process run in the background properly, the are KILLED right before calling execvp
my intuition tells me the problem is in the signal handler or the usage of return in the parent process after fork().
This is how I've implemented it (just for the background process) :
void ExeExternal(char *args[MAX], char* cmd,ExecutionMode ExeMode) {
int pID;
switch(pID = fork())
{
case -1:
// Add your code here (error)
/*
your code
*/
perror("fail to fork in : ExeExternal(...)\n");
exit(-1);
case 0 :
// Child Process
signal(SIGTSTP, SIG_DFL);
signal(SIGINT, SIG_DFL);
signal(SIGCONT, SIG_DFL);
usleep(20000);
setpgrp();
printf("trying to execvp\n");
int run_result=execvp(args[0],args);
if(run_result==-1)
{
perror("execvp(...) result in execvp\n");
exit(-1);
}
break; //wont reach this part ever!
default://the parent. pID holds child's pID
setpgid(pID, pID); //note, this is also done in the child
if(ExeMode==BACKGROUND) //no need to WAIT()
{
return;
}
}
}
and this is my signal handler (registered in my main() with signal(SIGCHLD,handle_sigchld)
void handle_sigchld(int sig) {
pid_t pid;
int status;
pid=waitpid(WAIT_ANY,&status,WUNTRACED | WNOHANG);
if (pid >0)
{
if(WIFEXITED(status)) //if terminated normally, return or exit
{
printf("\n[%d] %d Done \n", ID, pid); //‪[1‬] ‫‪a.out‬‬ ‫‪:‬‬ ‫‪12340‬‬ ‫‪214‬‬ ‫‪secs‬‬
}
else if (WIFSIGNALED(status)) //killed with SIGINT
{
printf("handle_sigchld:[%d] pid %d KILLED\n",ID,pid);
}
else if (WIFSTOPPED(status)) //suspended with SIGCONT
{
printf("\n[%d] %s %d %d secs (stopped)\n", ID, value,pid,time);
}
}
}
I've tried to plant some prinft's and my child seems to be killed right before executing execvp(...)
Ive tried to print the args[0] and args[1] and it exited there, so it looks like it falls upon accessing them,
also - is that the right way to use return ? ive tried to replace it with waitpid(pid,status,WNOHANG) but it didnt helped
ANY help is greatly appreciated! even just a hint in the right direction

child and parent process id

Just got confused with parent pid value in child process block. My program is given below:
int main(int argc, char *argv[])
{
pid_t pid;
pid=fork();
if(pid==-1){
perror("fork failure");
exit(EXIT_FAILURE);
}
else if(pid==0){
printf("pid in child=%d and parent=%d\n",getpid(),getppid());
}
else{
printf("pid in parent=%d and childid=%d\n",getpid(),pid);
}
exit(EXIT_SUCCESS);
}
Output:
pid in parent=2642 and childid=2643
pid in child=2643 and parent=1
In "Advanced Unix programming" it says that child process can get parent process id using getppid() function. But here I am getting "1" which is "init" process id.
How can I get the parent pid value in the child process block.. Please help me in getting output.
I executed in "Linux Mint OS" but in "WindRiver" OS I am not getting this problem. Does this program change behaviour according to OS?
That's because the father can / will exit before the son. If a father exists without having requested the return value of it's child, the child will get owned by the process with pid=1. What is on classic UNIX or GNU systems SystemV init.
The solution is to use waitpid() in father:
int main(int argc, char *argv[])
{
pid_t pid;
pid=fork();
if(pid==-1){
perror("fork failure");
exit(EXIT_FAILURE);
}
else if(pid==0){
printf("pid in child=%d and parent=%d\n",getpid(),getppid());
}
else{
printf("pid in parent=%d and childid=%d\n",getpid(),pid);
}
int status = -1;
waitpid(pid, &status, WEXITED);
printf("The child exited with return code %d\n", status);
exit(EXIT_SUCCESS);
}
After the fork you have two new processes and you can know the child id in the parent but not the other way round. If you really need this you would have to open a pipe (popen) before the fork and then the parent could write this into the pipe and the child could read it.
Once the parent completes it execution and child is still running. Then child is known as orphan (as it's parent died) and it is adopted by init process if you are login by root ( whose pid =1 ).
If you want child to exit first before parent then use wait() system call and its variants.
#include <stdio.h>
#include <unistd.h>
int main()
{
int pid,pid2;
pid=fork();
if (pid<0) {
printf("fork failed");
exit(-1);
} else if (pid==0) {
printf("child id is%d",getpid());
execlp("/bin/ls","is",NULL);
printf("\nsleeping for 2 seconds using pid of child class");
sleep(2);
printf("killing the child process");
kill(getpid());
} else {
wait(NULL);
printf("The parent id is %d\n",getpid());
printf("The child id is %d\n",getpid());
printf("\nsleeping for 3 seconds without pid");
sleep(3);
printf("\nchild completed\n");
exit(0);
}
}
It is simply, because the parent process no longer exists. If you call the wait() system function, then it will exist until the child finishes its work and you will get the parent PID.

Shell job control

For my school project I am implementing a shell and I need help with job control.
If we type a command, say cat &, then because of the & it should run in background, but it's not working. I have this code:
{
int pid;
int status;
pid = fork();
if (pid == 0) {
fprintf(stderr, "Child Job pid = %d\n", getpid());
execvp(arg1, arg2);
}
pid=getpid();
fprintf(stderr, "Child Job pid is = %d\n", getpid());
waitpid(pid, &status, 0);
}
Rather than just going straight to waiting, you should set up a signal handler for the SIGCHLD signal. SIGCHLD is sent whenever a child process stops or is terminated. Check out the GNU description of process completion.
The end of this article has a sample handler (which I've more or less copied and pasted below). Try modeling your code off of it.
void sigchld_handler (int signum) {
int pid, status, serrno;
serrno = errno;
while (1) {
pid = waitpid(WAIT_ANY, &status, WNOHANG);
if (pid < 0) {
perror("waitpid");
break;
}
if (pid == 0)
break;
/* customize here.
notice_termination is in this case some function you would provide
that would report back to your shell.
*/
notice_termination (pid, status);
}
errno = serrno;
}
Another good source of information on this subject is Advanced Programming in the UNIX Environment, chapters 8 and 10.
The parent process is calling waitpid on the child, which will block until the child process changes state (i.e. terminates).

understanding fork(), sleep() and processes flux

Been practicing with those system calls, but I stucked into this code:
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
main()
{
pid_t pid;
switch(pid = fork())
{
case -1:
printf("fork failed");
break;
case 0: //first child
printf("\ni'm the first child, my pid is %d", getpid());
fflush(stdout);
break;
default: //parent
sleep(5); /** sleep is generating problems **/
printf("\ni'm the parent process, my pid is %d", getpid());
printf("\ngenerating a new child");
fflush(stdout);
switch(pid = fork())
{
case -1:
printf("fork failed");
break;
case 0: //second child
printf("\nhere i am, the second child, my pid is %d", getpid());
break;
default: //parent
wait((int *)0);
printf("\nback to parent, my pid is %d", getpid());
}
}
return 0;
}
The output I'm getting is:
i'm the first child, my pid is 6203
i'm the parent process, my pid is 6202
generating a new child
back to parent, my pid is 6202
Process returned 0 (0x0) execution time: 5.004 s
Press ENTER to continue
here i am, the second child, my pid is 6204
What I'm trying it's a simple print of these messages managing the timing via sleep().
I can't understand why the program is returning before printing the second child message.
The default case(the one right after the second fork) got printed before its child(second) acting on the output like he's ignoring its wait(). Its child therefore got printed after the process returns.
I wasn't able to figure out what's the problem. I've marked sleep() function since if I substitute it with wait((int *)0); the processes flux is working how it was designed to (anyhow, without any timing).
At this point I'm not sure anymore about process flux, or the sleep() usage (man pages wasn't that helpful, way too concise to be honest).
Actually, your call to wait works. It detects the end of the first child process and continues afterwards. If you do two consecutive calls to wait(), you will get the proper behaviour.
Updated test code :
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
main()
{
pid_t pid;
int status;
switch(pid = fork())
{
case -1:
printf("fork failed");
break;
case 0: //first child
printf("\ni'm the first child, my pid is %d", getpid());
fflush(stdout);
break;
default: //parent
sleep(5); /** sleep is generating problems **/
printf("\ni'm the parent process, my pid is %d", getpid());
printf("\ngenerating a new child");
fflush(stdout);
switch(pid = fork())
{
case -1:
printf("fork failed");
break;
case 0: //second child
printf("\nhere i am, the second child, my pid is %d", getpid());
break;
default: //parent
pid = wait(&status);
printf("\nParent detects process %d was done", pid);
pid = wait(&status);
printf("\nParent detects process %d was done", pid);
printf("\nback to parent, my pid is %d", getpid());
}
}
return 0;
}
Output :
i'm the first child, my pid is 30897
i'm the parent process, my pid is 30896
generating a new child
here i am, the second child, my pid is 30940
Parent detects process 30897 was done
Parent detects process 30940 was done
back to parent, my pid is 30896
The man page for wait says the following:
The wait() function shall suspend execution of the calling thread until status information for one of the terminated child processes of the calling process is available, or until delivery of a signal whose action is either to execute a signal-catching function or to terminate the process. If more than one thread is suspended in wait() or waitpid() awaiting termination of the same process, exactly one thread shall return the process status at the time of the target process termination.
Wait is returning because of the first child.

Resources