Busybox udhcpd vfork starts two processes - c

In my application I require to start Busybox udhcpd (dhcp server), the code is below. While udhcpd does start and run I get two versions in the process list. udhcpd is running correctly, i.e. assigned IP addresses to devices.
pid_t forked_pid = vfork();
if ( forked_pid == 0 )
{
// Child process, execute udhcpd.
execl( "/usr/bin/udhcpd",
"udhcpd",
"/var/run/udhcpd.conf", // the location of the udhcpd config file
NULL );
}
else if ( forked_pid > 0 )
{
// Parent process, record the childs pid
m_udhcpd_pid = forked_pid;
log( Log_Info, "UDHCPD started with PID: %d (PID=%d)", forked_pid, getpid());
}
else
{
log( Log_Warning, "Failed to start UDHCPD" );
}
Log Output
UDHCPD started with PID: 647 (PID=528)
PS output
528 root 0:03 ./MyApp
647 root 0:00 [udhcpd]
648 root 0:00 udhcpd /var/run/udhcpd.conf
Now if I look at /var/run/udhcpd.pid it has the pid of 648. In another part of our code we start dhcpcd (dhcp client) using the same code as above and it only has one entry in the process list. Can anyone explain what the difference is and if I am doing things incorrectly what I should be doing?
The reason for asking is I require to later stop udhcpd and it seems I will need to stop using both the childs pid (647) and also the pid read from /var/run/udhcpd.pid (648).

I believe the answer is udhcpd does another fork leaving a zombie process. Reverted to just doing a system call and killing the process using the PID in the PID file.

Related

How to know if a process is a parent or a child

How does one identify if a process is a child/grandchild of another process using its pid?
Process IDs: Child- and parent processes
All running programs have a unique process ID. The
process ID, a
non-negative integer, is the only identifier of a process that is
always unique. But, process IDs are reused.
As a process terminates its ID becomes available for reuse. Certain
systems delay reuse so that newly created processes are not confused
with old ones.
Certain IDs are "reserved" in the sense that they are being used by
system processes, such as the scheduler process. Another example is
the init process that always occupies PID 1. Depending on the system
the ID might be actively reserved.
Running the commands
> ps -eaf | head -n 5
UID PID PPID C STIME TTY TIME CMD
root 1 0 0 11:49 ? 00:00:02 /sbin/init splash
root 2 0 0 11:49 ? 00:00:00 [kthreadd]
root 3 2 0 11:49 ? 00:00:00 [ksoftirqd/0]
root 5 2 0 11:49 ? 00:00:00 [kworker/0:0H]
and
> pidof init
1
will allow you to independently verify this.1
In C we can use the following functions to get the process ID of the
calling process and the parent process ID of the calling process,
#include <unistd.h>
pid_t getpid(void);
pid_t getppid(void);
A process can create other processes. The created processes are called
"child processes" and we refer to the process that created them as
the "parent process".
Creating a new process using fork()
To create a child process we use the system call
fork()
#include <unistd.h>
pid_t fork(void);
The function is called once, by the parent process, but it returns
twice. The return value in the child process is 0, and the return
value in the parent process is the process ID of the new child.1
A process can have multiple child processes but there is no system
call for a process to get the process IDs of all of its children, so
the parent observes the return value of the child process and can use
these identifiers to manage them.
A process can only have a single parent process, which is always
obtainable by calling getppid.
The child is a copy of the parent, it gets a copy of the parent's
data space, heap and stack. They do not share these portions of
memory! 2
We will compile and execute the following code snippet to see how
this works,
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/syscall.h>
int main(void) {
int var = 42; // This variable is created on the stack
pid_t pid;
// Two processes are created here
// v~~~~~~~~~~|
if ((pid = fork()) < 0) {
perror("Fork failed");
} else if (pid == 0) { // <- Both processes continue executing here
// This variable gets copied
var++;
printf("This is the child process:\n"
"\t my pid=%d\n"
"\t parent pid=%d\n"
"\t var=%d\n", getpid(), getppid(), var);
} else {
printf("This is the parent process:\n"
"\t my pid=%d\n"
"\t child pid=%d\n"
"\t var=%d\n", getpid(), pid, var);
}
return 0;
}
We will see when we execute the program that there are no guarantees
as to which process gets to execute first. They may even operate
simultaneously, effectively interleaving their output. 3
$ # Standard compilation
$ gcc -std=c99 -Wall fork_example1.c -o fork_example1
$ # Sometimes the child executes in its entirety first
$ ./fork_example1
This is the child process:
my pid=26485
parent pid=26484
var=43
This is the parent process:
my pid=26484
child pid=26485
var=42
$ # and sometimes the parent executes in its entirety first
$ ./fork_example1
This is the parent process:
my pid=26461
child pid=26462
var=42
This is the child process:
my pid=26462
parent pid=26461
var=43
$ # At times the two might interleave
$ ./fork_example1
This is the parent process:
my pid=26455
This is the child process:
my pid=26456
parent pid=26455
var=43
child pid=26456
var=42
1 PID stands for Process ID and PPID stands for
Parent Process ID.
2 The process ID 0 is reserved for use by the kernel, so
it is not possible for 0 to be the process ID of a child.
3 Many systems do not perform a complete copy of these
memory segments and instead only creates a copy when either process
performs a write. Initially, the shared regions are marked by the
kernel as "read-only" and whenever a process tries to modify these
regions the kernel awards each process their own copy of that memory.
4 Standard out is buffered so it's not a perfect example.
Use getpid() and getppid() function to get process id and parent process id.

getpid() incremented by 5 or 6 every time a.out is executed

I'm working on Advanced Programming in the UNIX Environment 3rd edition, problem 1 in chapter 1.
Under OS X 10.10.5, why might the value returned by getpid() be incremented by 5 or 6 every time the process executed? (In the book, it might increment by 2.)
And why does the value returned by getppid() remain the same?
> cat getpid.c
int main()
{
printf("pid: %d\n", getpid());
printf("ppid: %d\n", getppid());
exit(0);
}
> g++ getpid.c
> ./a.out
pid: 9411
ppid: 6469
> ./a.out
pid: 9416
ppid: 6469
> ./a.out
pid: 9421
ppid: 6469
>
gettppid returns the parent process id - that is the process id of the shell you are running under. Since you keep launching a.out from the same parent process, it will keep returning the same process id. Does that make sense? Go open another terminal window and run a.out. getppid will be different on that terminal window.
getpid return the process id of the instance of a.out your running. Every process id is unique, but there's nothing in any standard that says these numbers must be incremental or assigned in a predictable manner.
The operating system assigns PIDs as it sees fit. There are no guarantees made about what PID your process might get, except that it be unique at any given point in time. This is what getpid gives you.
The parent process of your program – as you run it – is the current shell you're working in. Since it is the same process every time, it always has the same PID. This is the value returned by getppid.

Program control does not return after multiple forks leaving zombie and process hanging

Trying to simulate the functionality of the | command line argument in Linux. I've already parsed the arguments properly but program control is not returning to my main process and I've got one uninterruptible process and a zombie - which I don't understand how since I figured if I spawned the processes they should terminate on their own as they are just regular linux processes. I added the processes below. I'm just running ps aux | grep notepad. I posted previously here How do I create a grep process with fork that will accept data from a pipe in Linux C programming but this issue is different as I have the correct output I just don't want the processes to hang.
1000 4074 0.0 0.0 4392 824 pts/0 S+ 21:38 0:00 grep notepad
1000 4075 0.0 0.0 0 0 pts/0 Z+ 21:38 0:00 [ps] <defunct>
1000 4076 0.0 0.0 4944 1172 pts/0 R+ 21:38 0:00 ps aux
int ppid = fork ();
if(ppid == 0)
{
pid = fork();
//Parent assume execution control
if(ppid == 0 && pid != 0)
{
//Close the parents in and redirect to pipe
close(0);
dup(pfds[0]);
close(pfds[1]);
execvp(secondargs[0], secondargs);
perror("exect failed to");
exit(-1);
}
//C1 execute first line of command line
else if(pid == 0)
{
close(1); //close stdout
dup(pfds[1]); // make stdout pfds[1]
close(pfds[0]);
//execute the args
execvp(args[0], args);
perror("exec failed to");
exit(-1);
}
}
Processes must be wait()ed for. The zombie entry exists to retain the process return code until the wait() picks it up, since the RC might carry important information about how the child process exited.
If you don't want to deal with keeping appropriate wait()s spinning until the children exit, one standard trick is to "double fork" -- spawn an intermediate process which launches the desired child process and then kills itself. That results in the child being disowned, at which point it becomes child of the system process and the system-default wait() handling takes over to absorb the zombie and discard the return code.
Websearch for "unix fork zombie wait", or some combination of those terms, will find examples and more extensive discussion of the issue.
I'm fairly sure that the problem is that you create the pipe before you fork any children (since there is no pipe() call in the code fragment).
Unfortunately, you don't close the pipe in the original parent process, so it can still write to the write end of the pipe. Therefore, even though the ps has exited, the system knows that the parent could still write on the pipe (even though it won't) so grep never gets told EOF.
In other words, grep is waiting for the original parent process to close the pipe, and the original parent process is waiting for grep to finish (or, at least, it might be). If the original parent exits, then grep will get EOF and will exit, and the system will clean up both corpses. If the original parent is waiting, then it is going to wait for a very long time.

C Fork Stray Process

I am using fork & have a problem where if 1 branch exits, the others are left stray.
By "stray", I mean I am back in bash & can type in system commands, but the server is constantly outputting on top of my cursor.
The code used to work by killing both branches if I ^c. Since adding sockets into the mix, a client disconnecting caused the server to go stray.
Anyone have ideas as to why?
In my main() :
printf("\n Server Running Press ^c to quit\n\n");
if (!fork()) { // Debug output
while (1) {
// Do output stuff until ^c signal
fflush(stdout);
}
} else { // Internets
while (1) {
clfd=accept(listenfd, (struct sockaddr*)&claddr, &claddrlen);
if (!fork()) { // Listener
close(clfd);
} else { // Communication branch
num=rand()%16;
//i=recv(clfd, &num, sizeof(num), 0);
send(clfd, &num, 1, 0);
close(clfd);
exit(0);
}
}
exit(0);
}
return 0;
This is from ps:
PID TTY TIME CMD
11159 pts/8 00:00:00 sv_run
11899 pts/8 00:00:00 sv_run
11987 pts/8 00:00:00 ps
21687 pts/8 00:00:01 bash
This is is part of the pstree:
|-sshd---sshd---csh
|-sshd---bash---top
|-2*[sv_run]
|-8*[trashapplet]
|-udevd---udevd
When you press Control+C, you kill the process that have created multiple child processes. Killing the parent does not, by default, kill child processes, and therefore they continue to run while you continue working in the terminal. And because all of the processes share the same output device, the output is interleaved.
I am not sure what do you actually expect your code to do. Neither I know what platform you are using. But if it so happens that you want kill the process and all of its children on SIGINT and you are using Linux, then you can ask the kernel to deliver SIGHUP upon death of the parent in your child processes. For more details on how to do this, see How to make child process die after parent exits?
Alternative, you have to make your server kill of its child processes on exit, for example, by using a custom SIGINT signal handler.
Hope it helps. Good Luck!

how to view current process state in program output itself

how to print the current process state
main ()
{
pid_t pid;
printf("parent : %d\n", getpid());
pid = fork();
if (pid == 0)
{
printf("child : %d\n", getpid());
sleep(2);
printf("child exit\n");
exit(1);
}
while (1)
{ /*after the child exit, its a zombie process */
system("clear");
system("ps -x | grep t"); /* if a.out is Z means zombie process */
sleep(8);
}
}
Is there any other method or way to view the current process state in output
itself..?
Determining the scheduling state of a process is OS specific. On Linux, top and similar read it from the third field in /proc/$PID/stat.
You can always open and read /proc files in C
/proc/[pid]/stat and /proc/[pid]/status would give the status of the current proces.
The third field in /proc/<pid>/stat contains the process status: R if it's Running, S if it's Sleeping (there's a few others too, like D for Disk Wait and Z for Zombie).
Or you can parse the output of ps command using popen. But remember ps command itself is implemented based on the information from /proc filesystem

Resources