I have the following code:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main()
{
for(int i=0;i<3;i++)
{
int cpid=fork();
if(cpid==0)
printf("I am a child with id %d, and my parent is %d\n",getpid(),getppid());
else
printf("I am a parent with id %d\n",getpid());
}
}
I am trying to form a process tree. The output is:
I am a parent with id 9494
I am a parent with id 9494
I am a child with id 9495, and my parent is 9494
I am a parent with id 9494
I am a child with id 9496, and my parent is 9494
I am a parent with id 9495
I am a parent with id 9496
I am a parent with id 9495
I am a child with id 9498, and my parent is 9495
I am a parent with id 9498
I am a child with id 9499, and my parent is 3004
I am a child with id 9497, and my parent is 3004
I am a child with id 9500, and my parent is 3004
I am a child with id 9501, and my parent is 3004
I cannot figure out where is the process with id 3004 coming in. How many total processes are created as a result of this code? What will be the final process tree? I am beginner.
I'll help with the mystery of process 3004. The rest should be reasonably easy to figure out on your own (you might want to add cpid to the second printf() to help with that).
I am a child with id 9499, and my parent is 3004
What happened here is that the original parent of process 9499 had died before 9499 had a chance to call getppid(). When the parent of a process dies, that process gets re-parented. In your case, the new parent's pid is 3004. This process is not part of the process tree created by your program (it probably sits somewhere above it in the overall process tree), so you don't see a "I am a parent with id" for it.
Here is some relevant reading: process re-parenting: controlling who is the new parent.
Try this piece of code.
The output of this code will explain alot more things to you. Some of the processes print their respective printf function after their parent process died. These processes(orphan process) are adopted by some other processes. That could be the reason for a peculiar pid being printed by printf function. Also, there is a race-condition between creation of processes and printing of their respective pid which can be seen in the output of the code below.
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main()
{
printf("Main\n");
for(int i=0;i<3;i++) {
printf("Loop index - %d and pid is - %d\n", i, getpid());
int cpid=fork();
if(cpid==0)
printf("I am a child with id %d, and my parent is %d with loop index - %d\n",getpid(),getppid(), i);
else
printf("I am a parent with id %d and with loop index - %d\n",getpid(), i);
}
printf("Terminated - %d\n", getpid());
return 0;
}
Related
so I wanted to write a programme where i will create multi level child processes. With single parent and single child.
example: Parent->child1->child2->child3. like that.
See image here
But the problem is I want to take input from terminal how many child processes will be created (single parent - single Child processes).
So How Can I modify that Nested if statement to some loop such that it will create child processes as i wanted it to be.
so Here goes My code
#include<stdio.h>
#include<stdlib.h>
#include<stdio.h>
#include<sys/types.h>
#include<unistd.h>
int main() {
int a, b;
{
if(fork() == 0)
{
printf("child my pid is %d ppid is %d\n",getpid(),getppid());
if(fork()== 0)
{
printf("child my pid is %d ppid is %d\n",getpid(),getppid());
if(fork()== 0)
{
printf("child my pid is %d ppid is %d\n",getpid(),getppid());
}
}
}
else
printf("father my pid is %d ppid is %d\n",getpid(),getppid());
}
for(int i=0;i<3;i++)
wait(NULL);
return 0;
}
OUTPUT GOES HERE:
father my pid is 4496 ppid is 3621
child my pid is 4497 ppid is 4496
child my pid is 4498 ppid is 4497
child my pid is 4499 ppid is 4498
Thanks It's working finally.
Just loop it:
#include <stdio.h>
#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <assert.h>
int main(int argc, char *argv[])
{
assert(argc == 2);
int num = atoi(argv[1]);
for (int i = 0; i < num; ++i) {
int child;
switch ((child = fork())) {
case 0:
printf("child my pid is %d ppid is %d\n", getpid(), getppid());
break;
case -1:
fprintf(stderr, "fork failed\n");
break;
default:
printf("father my pid is %d ppid is %d and i just created %d\n",getpid(), getppid(), child);
i = num; // break of loop
break;
}
}
wait(NULL);
return 0;
}
#edit:
The break of loop was in the wrong place. Now the process creates a tree of processes as intended:
Compiled the code using gcc and run:
$ ./a.out 5
father my pid is 21893 ppid is 21640 and i just created 21894
child my pid is 21894 ppid is 21893
father my pid is 21894 ppid is 21893 and i just created 21895
child my pid is 21895 ppid is 21894
father my pid is 21895 ppid is 21894 and i just created 21896
child my pid is 21896 ppid is 21895
father my pid is 21896 ppid is 21895 and i just created 21897
child my pid is 21897 ppid is 21896
father my pid is 21897 ppid is 21896 and i just created 21898
child my pid is 21898 ppid is 21897
The program:
starts as pid 21893
creates child with pid 21894
child 21894 creates child 21895
child 21895 creates child 21896
child 21896 creates child 21897
child 21907 creates child 21898
With fork() operation child process inherits attribute real and effective user Id's from parent process, how it behaves when exec() is performed ?
Exec does not change any of them. From the linux manual :
The exec() family of functions replaces the current process image with a new process image.
The exec changes the process image (the code and data segment in memory), but it does not change the process descriptor of the new process created with fork. The process descriptor contains the real and effective id, because this is not changed by an exec call, the effective and real id are not changed neither.
I hope that I have been clear explaining the concept.
The real and effective UID and GID of the child process are equal to the real and effective UID and GID of the parent process. Therefore, when the child process calls exec those values are not modified.
In order to prove this I wrote a small application that creates a child process which calls exec. The exec system call runs an application that prints out the value of the GID and UID of the current process. In addition the GID and UID of the parent process are showen as well, so that we can compare them.
main.c
#include <stdio.h>
#include <unistd.h>
void print_info () {
printf(" UID GID \n"
"Real %d Real %d \n"
"Effective %d Effective %d \n",
getuid (), getgid (),
geteuid(), getegid()
);
return;
}
int main () {
pid_t pid;
int status;
pid = fork();
if (!pid) {
puts("Childe process\n");
execv("./uid.out", NULL);
return;
}
wait(status);
printf("Father %d -------------------\n", getpid());
print_info();
puts("--------------------------------");
return 0;
}
uid.c
#include <stdio.h>
#include <unistd.h>
int main () {
printf("CHILD %d -------------------\n", getpid());
printf(" UID GID \n"
"Real %d Real %d \n"
"Effective %d Effective %d \n",
getuid (), getgid (),
geteuid(), getegid()
);
puts("---------------------------------");
return 0;
}
Output :
CHILD 17436 -------------------
UID GID
Real 1000 Real 1000
Effective 1000 Effective 1000
---------------------------------
Father 17435 -------------------
UID GID
Real 1000 Real 1000
Effective 1000 Effective 1000
--------------------------------
Let me know if you need more info.
Wikipedia says "A child process that terminates but is never waited on by its parent becomes a zombie process." I run this program:
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
int main()
{
pid_t pid, ppid;
printf("Hello World1\n");
pid=fork();
if(pid==0)
{
exit(0);
}
else
{
while(1)
{
printf("I am the parent\n");
printf("The PID of parent is %d\n",getpid());
printf("The PID of parent of parent is %d\n",getppid());
sleep(2);
}
}
}
This creates a zombie process, but I can't understand why a zombie process is created here?
The output of the program is
Hello World1
I am the parent
The PID of parent is 3267
The PID of parent of parent is 2456
I am the parent
The PID of parent is 3267
The PID of parent of parent is 2456
I am the parent
....
.....
But why is it that the "child process terminates but is not waited on by its parent" in this case?
In your code, zombie is created on exit(0) (comment with arrow below):
pid=fork();
if (pid==0) {
exit(0); // <--- zombie is created on here
} else {
// some parent code ...
}
Why? Because you never waited on it. When something calls waitpid(pid), it returns postmortem information about process, like its exit code. Unfortunately, when process exited, kernel cannot just dispose of this process entry, or return code will be lost. So it waits for somebody to wait on it, and leaves this process entry around even if it does not really occupy any memory except for entry in process table - this is exactly what is called zombie.
You have few options to avoid creating zombies:
Add waitpid() somewhere in the parent process. For example, doing this will help:
pid=fork();
if (pid==0) {
exit(0);
} else {
waitpid(pid); // <--- this call reaps zombie
// some parent code ...
}
Perform double fork() to obtain grandchild and exit in child while grandchild is still alive. Grandchildren will be automatically adopted by init if their parent (our child) dies, which means if grandchild dies, it will be automatically waited on by init. In other words, you need to do something like this:
pid=fork();
if (pid==0) {
// child
if (fork()==0) {
// grandchild
sleep(1); // sleep a bit to let child die first
exit(0); // grandchild exits, no zombie (adopted by init)
}
exit(0); // child dies first
} else {
waitpid(pid); // still need to wait on child to avoid it zombified
// some parent code ...
}
Explicitly ignore SIGCHLD signal in parent. When child dies, parent gets sent SIGCHLD signal which lets it react on children death. You can call waitpid() upon receiving this signal, or you can install explicit ignore signal handler (using signal() or sigaction()), which will make sure that child does not become zombie. In other words, something like this:
signal(SIGCHLD, SIG_IGN); // <-- ignore child fate, don't let it become zombie
pid=fork();
if (pid==0) {
exit(0); // <--- zombie should NOT be created here
} else {
// some parent code ...
}
I have a bunch of mini-server processes running. They're in the same process group as a FastCGI server I need to stop. The FastCGI server will kill everything in its process group, but I need those mini-servers to keep running.
Can I change the process group of a running, non-child process (they're children of PID 1)? setpgid() fails with "No such process" though I'm positive its there.
This is on Fedora Core 10.
NOTE the processes are already running. New servers do setsid(). These are some servers spawned by older code which did not.
One thing you could try is to do setsid() in the miniservers. That will make them session and process group leaders.
Also, keep in mind that you can't change the process group id to one from another session, and that you have to do the call to change the process group either from within the process that you want to change the group of, or from the parent of the process.
I've recently written some test code to periodically change the process group of a set of processes for a very similar task. You need not change the group id periodically, it's just that I thought I might evade a certain script that periodically checked for a group that runs for longer than a certain amount of time. It may also help you track down the error that you get with setpgid():
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <string.h>
void err(const char *msg);
void prn(const char *msg);
void mydaemon();
int main(int arc, char *argv[]) {
mydaemon();
if (setsid() < 0)
err("setsid");
int secs = 5*60;
/* creating a pipe for the group leader to send changed
group ids to the child */
int pidx[2];
if (pipe(pidx))
err("pipe");
fcntl(pidx[0], F_SETFL, O_NONBLOCK);
fcntl(pidx[1], F_SETFL, O_NONBLOCK);
prn("begin");
/* here the child forks, it's a stand in for the set of
processes that need to have their group ids changed */
int child = fork();
switch (child) {
case -1: err("fork3");
case 0:
close(pidx[1]);
while(1) {
sleep(7);
secs -= 7;
if (secs <= 0) { prn("end child"); exit(0); }
int pid;
/* read new pid if available */
if (read(pidx[0], &pid, sizeof pid) != sizeof pid) continue;
/* set new process group id */
if (setpgid(getpid(), pid)) err("setpgid2");
prn("child group changed");
}
default: break;
}
close(pidx[0]);
/* here the group leader is forked every 20 seconds so that
a new process group can be sent to the child via the pipe */
while (1) {
sleep(20);
secs -= 20;
int pid = fork();
switch (pid) {
case -1: err("fork2");
case 0:
pid = getpid();
/* set process group leader for this process */
if (setpgid(pid, pid)) err("setpgid1");
/* inform child of change */
if (write(pidx[1], &pid, sizeof pid) != sizeof pid) err("write");
prn("group leader changed");
break;
default:
close(pidx[1]);
_exit(0);
}
if (secs <= 0) { prn("end leader"); exit(0); }
}
}
void prn(const char *msg) {
char buf[256];
strcpy(buf, msg);
strcat(buf, "\n");
write(2, buf, strlen(buf));
}
void err(const char *msg) {
char buf[256];
strcpy(buf, msg);
strcat(buf, ": ");
strcat(buf, strerror(errno));
prn(buf);
exit(1);
}
void mydaemon() {
int pid = fork();
switch (pid) {
case -1: err("fork");
case 0: break;
default: _exit(0);
}
close(0);
close(1);
/* close(2); let's keep stderr */
}
After some research I figured it out. Inshalla got the essential problem, "you can't change the process group id to one from another session" which explains why my setpgid() was failing (with a misleading message). However, it seems you can change it from any other process in the group (not necessarily the parent).
Since these processes were started by a FastCGI server and that FastCGI server was still running and in the same process group. Thus the problem, can't restart the FastCGI server without killing the servers it spawned. I wrote a new CGI program which did a setpgid() on the running servers, executed it through a web request and problem solved!
It sounds like you actually want to daemonise the process rather than move process groups. (Note: one can move process groups, but I believe you need to be in the same session and the target needs to already be a process group.)
But first, see if daemonising works for you:
#include <unistd.h>
#include <stdio.h>
int main() {
if (fork() == 0) {
setsid();
if (fork() == 0) {
printf("I'm still running! pid:%d", getpid());
sleep(10);
}
_exit(0);
}
return 0;
}
Obviously you should actually check for errors and such in real code, but the above should work.
The inner process will continue running even when the main process exits. Looking at the status of the inner process from /proc we find that it is, indeed, a child of init:
Name: a.out
State: S (sleeping)
Tgid: 21513
Pid: 21513
PPid: 1
TracerPid: 0
Can child process use the ptrace system call to trace its parent?
Os is linux 2.6
Thanks.
upd1:
I want to trace process1 from "itself". It is impossible, so I do fork and try to do ptrace(process1_pid, PTRACE_ATTACH) from child process. But I can't, there is a strange error, like kernel prohibits child from tracing their parent processes
UPD2: such tracing can be prohibited by security policies. Which polices do this? Where is the checking code in the kernel?
UPD3: on my embedded linux I have no errors with PEEKDATA, but not with GETREGS:
child: getregs parent: -1
errno is 1, strerror is Operation not permitted
errno = EPERM
This question really interested me. So I wrote some code to try it out.
Firstly keep in mind, that when tracing a process, the tracing process becomes a parent for most purposes, except in name (i.e. getppid()). Firstly, a snippet of the PTRACE_ATTACH section of the manual is helpful:
PTRACE_ATTACH
Attaches to the process specified in pid, making it a traced
"child" of the calling process; the behavior of the child is as
if it had done a PTRACE_TRACEME. The calling process actually
becomes the parent of the child process for most purposes (e.g.,
it will receive notification of child events and appears in
ps(1) output as the child's parent), but a getppid(2) by the
child will still return the PID of the original parent. The
child is sent a SIGSTOP, but will not necessarily have stopped
by the completion of this call; use wait(2) to wait for the
child to stop. (addr and data are ignored.)
Now here is the code I wrote to test and verify that you can in fact ptrace() your parent (you can build this by dumping it in a file named blah.c and running make blah:
#include <assert.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/ptrace.h>
int main()
{
pid_t pid = fork();
assert(pid != -1);
int status;
long readme = 0;
if (pid)
{
readme = 42;
printf("parent: child pid is %d\n", pid);
assert(pid == wait(&status));
printf("parent: child terminated?\n");
assert(0 == status);
}
else
{
pid_t tracee = getppid();
printf("child: parent pid is %d\n", tracee);
sleep(1); // give parent time to set readme
assert(0 == ptrace(PTRACE_ATTACH, tracee));
assert(tracee == waitpid(tracee, &status, 0));
printf("child: parent should be stopped\n");
printf("child: peeking at parent: %ld\n", ptrace(PTRACE_PEEKDATA, tracee, &readme));
}
return 0;
}
Note that I'm exploiting the replication of the parent's virtual address space to know where to look. Also note that when the child then terminates, I suspect there's an implicit detach which must allow the parent to continue, I didn't investigate further.
Yes it is possible...
Even GETREGS works.
Checked on x86
(based on Matt Joiner code, thanks him)
#include <assert.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/ptrace.h>
#include <sys/types.h>
#include <sys/user.h>
int main()
{
pid_t pid = fork();
// assert(pid != -1);
int status;
long readme = 0;
struct user_regs_struct regs;
if (pid)
{
readme = 42;
printf("parent: child pid is %d\n", pid);
assert(pid == wait(&status));
printf("parent: child terminated?\n");
assert(0 == status);
}
else
{
pid_t tracee = getppid();
printf("child: parent pid is %d\n", tracee);
sleep(1); // give parent time to set readme
assert(0 == ptrace(PTRACE_ATTACH, tracee));
assert(tracee == waitpid(tracee, &status, 0));
printf("child: parent should be stopped\n");
printf("child: peeking at parent: %ld\n", ptrace(PTRACE_PEEKDATA, tracee, &readme, NULL));
printf("Regs was %p, %p, %p, %p; &status is %p \n", regs.eax, regs.ebx, regs.ecx, regs.edx, &status);
printf("child: getregs parent: %ld\n", ptrace(PTRACE_GETREGS, tracee, NULL, ®s));
printf("Regs is %p, %p, %p, %p; &status is %p \n", regs.eax, regs.ebx, regs.ecx, regs.edx, &status);
}
return 0;
}
result:
child: parent pid is 1188
parent: child pid is 1189
child: parent should be stopped
child: peeking at parent: 42
Regs was (nil), (nil), (nil), (nil); &status is 0xbfffea50
child: getregs parent: 0
Regs is 0xfffffe00, 0xffffffff, 0xbfffea50, (nil); &status is 0xbfffea50
parent: child terminated?