fork() not behaving as expected - fork

I'm expecting my fork() to allow my child processes to print where they are in the loop to test my round robin scheduling algorithm, but the count is never printed. More specifically, the parent process executes all and I never see a print from my child. Any ideas why? I might be misunderstanding the use of fork() or wait() still.
for (i = 0; i < 64; i++)
{
pid = fork();
if (pid < 0) {
cprintf("fork failed\n");
return -1;
} else if (pid > 0) {
cprintf("Parent: child process has pid: %d\n", pid);
wait();
cprintf("Parent: child process %d has completed\n", pid);
} else if (pid == 0) {
for (int n = 0; n < 1000; n++)
{
cprintf("Child: this child is at %d in the loop", n);
}
exit();
}
}
Thanks.
EDIT:
The output is as follows
$ testscheduler
Test Scheduler
Round Robin Test
Parent: child process has pid: 4
Parent: child process 4 has completed
Parent: child process has pid: 5
Parent: child process 5 has completed
Parent: child process has pid: 6
Parent: child process 6 has completed
Parent: child process has pid: 7
Parent: child process 7 has completed
Parent: child process has pid: 8
Parent: child process 8 has completed
Parent: child process has pid: 9
Parent: child process 9 has completed
Parent: child process has pid: 10
Parent: child process 10 has completed
Parent: child process has pid: 11
Parent: child process 11 has completed
...
...
...
Parent: child process has pid: 66
Parent: child process 66 has completed
Parent: child process has pid: 67
Parent: child process 67 has completed

Your user mode program seems to work.
I would suspect your modified scheduling algorithm, please edit your post with more information.

Related

Why different pids from fork() and getpid()?

My homework asks this:
Using the program below, identify the values of pid at lines A, B, C, and D. (Assume that the actual pids of the parent and child are 10 and 20, respectively.) Explain for each line the reason for the pid value.
#include <sys/types.h>
#include <stdio.h>
#include <unistd.h>
int main() {
pid_t pid, pid1;
/* fork a child process */
pid = fork();
if (pid < 0) { /* error occurred */
fprintf(stderr, "Fork Failed\n");
return 1;
}
else if (pid == 0) { /* child process */
pid1 = getpid();
printf("child: pid = %d\n",pid); /* A */
printf("child: pid1 = %d\n",pid1); /* B */
}
else { /* parent process */
pid1 = getpid();
printf("parent: pid = %d\n",pid); /* C */
printf("parent: pid1 = %d\n",pid1); /* D */
wait(NULL);
}
return 0;
}
When I run it I get (for example):
parent: pid = 1586
parent: pid1 = 1585
child: pid = 0
child: pid1 = 1586
Why does fork() and getpid() return different pids for what's supposedly the same process?
You should first understand the return values of both function:
fork returns 0 in the child process and a non-zero value in the parent process; this non-zero value is the child process' PID.
getpid returns the PID of the current process; current means whoever is calling the getpid function.
First, in your code, even though the line pid1 = getpid() is the same, the caller is different. In the else if block it was the child process, and in the else block it was the parent. Therefore the two pid1s are different in the output.
Second, in the parent process, pid (fork's return value) is the child process' PID, not itself's. The reason fork returns child process' PID is to allow the parent process to communicate with and control the child.

Fork/ execlp in #pragma omp parallel for stops arbitrarily

I am programming a Kalman-Filter based realtime program in C using a large number of realizations. To generate the realization output I have to execute an external program (groundwater simulation software) about 100 times. I am therefore using OpenMP with fork and exceclp for parallelization of this block:
#pragma omp parallel for private(temp)
for(i=1;i<=n_real;i++){
/* Start ensemble model run */
int = fork();
int ffork = 0;
int status;
if (pid == 0) {
//Child process
log_info("Start Dadia for Ens %d on thread %d",i,omp_get_thread_num());
sprintf(temp,"ens_%d",i);
chdir(temp);
execlp("../SPRING/dadia","dadia","-return","-replace_kenn","73","ini.csv","CSV",NULL);
log_info("Could not execute function dadia - exit anyway");
ffork = 1;
_exit(1);
}
else{
//Parent process
wait(NULL);
if (ffork == 0){
log_info("DADIA run ens_%d successfully finished",i);
}
}
}
In general the code runs smoothly for small number of realizations (with 6 threads). However sometimes the code hangs in the last cycle of parallel iterations. The occurrence only happens if number iterations >> number threads. I tried scheduling the for loop with different options, but it didn't solve the problem. I know that fork is not the best solution to use with OpenMP. But I am wondring why it's sometimes hangs at arbitrary points.
Thank's a lot for any kind if feedback.
Different Ubuntu versions tried (including difffrent comiler versions)
This version finally seems to run stable. Thank's for your hints:
#pragma omp parallel for private(temp) schedule(dynamic)
for(i=1;i<=n_real;i++) {
/* Start ensemble model run */
/* Calling bash-commands inside OpenMP enviroment requires using fork().
Else the parallel process is terminated.
Note exec automatically ends the child process after termination.
If Sitra fails, the child process needs to be terminated manually */
pid_t pid = 0;
int status;
pid = fork();
if (pid == 0) {
log_info("Start SITRA for Ens %d on thread %d",i,omp_get_thread_num());
sprintf(temp,"ens_%d",i);
chdir(temp);
execl("../SPRING/sitra","sitra","-return",(char *) 0);
perror("In exec(): ");
}
if (pid > 0) {
pid = wait(&status);
log_info("End of sitra for ensemble %d",i);
if (WIFEXITED(status)) {
printf("Sitra ended with exit(%d).\n", WEXITSTATUS(status));
}
if (WIFSIGNALED(status)) {
printf("Sitra ended with kill -%d.\n", WTERMSIG(status));
}
}
if (pid < 0){
perror("In fork():");
}
}

fork, execlp, kill and waitpid with fbi but still ending up with zombies

I'm running Pi OS Bullseye on a Pi4 and I'm trying to do the following:
Run a systemd service
Have that service display images (child process C1 exec fbi)
On demand, display next images (child process C2 exec fbi) and tidy up
To this end, the parent process (P) and child attempt this:
P: fork a child (C2)
C2: exec fbi
P: kill and waitpid the previous fbi instance of C1
I get a left-over process and a zombie is killed then new one created every time I run the sequence - it looks like fbi itself forks another child (C3).
My ps output looks like this:
PID PPID PGRP USER NI S COMMAND
5706 1 5706 root -5 S fbi
5705 5499 5499 root -5 Z fbi
5704 1 5704 root -5 S fbi
5702 1 5702 root -5 S fbi
5700 1 5700 root -5 S fbi
5698 1 5698 root -5 S fbi
5696 1 5696 root -5 S fbi
5694 1 5694 root -5 S fbi
If I manually kill an old instance of fbi (e.g. 5694 in the above trace) they all die, which makes me think this is a peculiarity with fbi.
Also, my app reported 5705 as the forked process - what is 5706?
And how is PID 1 launching fbi (PID 5706) instead of my app (PID 5499)?
I could ignore the zombie as there is only a single instance. If there are multiple new image requests (and another display) the number of running fbi instances will mount up.
I've also tried using Process Groups (setgid, killpg) with the same outcome.
Can someone please explain what I'm doing wrong? This is beginning to hurt.
My code (display_front_img is called - yes, there will be more displays) -
void show_image(char *fb_dev_file, char *img_path, pid_t forked_pid, pid_t last_pid)
{
if(forked_pid == 0) // child executes fbi
{
execlp("/usr/bin/fbi", "fbi", "-d", fb_dev_file, "-T", "1", "--noverbose", img_path, NULL);
}
// parent cleans up
else if(last_pid != 0) // if previous fbi called
{
fprintf(stderr, "kill %d returned %d\n", last_pid, kill(last_pid, SIGTERM));
fprintf(stderr, "wait %d returned %d\n", last_pid, waitpid(last_pid, NULL, 0));
}
}
void display_front_img(char * img_path)
{
pid_t last_pid = front_fbi_pid; // get previous assigned PID
front_fbi_pid = fork(); // get newly assigned PID or 0
show_image("/dev/fb0", img_path, front_fbi_pid, last_pid);
}

Child process won't suicide if parent dies

I have a subprocess (running on MacOS) that I want to kill itself if the parent quits, exits, terminates, is killed or crashes. Having followed the advice from How to make child process die after parent exits? I can't get it to quietly kill itself if the parent program crashes. It will go to 100% CPU until I manually kill it.
Here are the key points of the code:
int main(int argc, char *argv[])
{
// Catch signals
signal(SIGINT, interruptHandler);
signal(SIGABRT, interruptHandler);
signal(SIGTERM, interruptHandler);
signal(SIGPIPE, interruptHandler);
// Create kqueue event filter
int kqueue_fd = kqueue();
struct kevent kev, recv_kev;
EV_SET(&kev, parent_pid, EVFILT_PROC, EV_ADD|EV_ENABLE, NOTE_EXIT, 0, NULL);
kevent(kqueue_fd, &kev, 1, NULL, 0, NULL);
struct pollfd kqpoll;
kqpoll.fd = kqueue_fd;
kqpoll.events = POLLIN;
// Start a run loop
while(processEvents())
{
if(kill(parent_pid, 0) == -1)
if(errno == ESRCH)
break;
if(poll(&kqpoll, 1, 0) == 1)
if(kevent(kqueue_fd, NULL, 0, &recv_kev, 1, NULL))
break;
parent_pid = getppid();
if(parent_pid == 1)
break;
sleep(a_short_time);
// (simple code here causes subprocess to sleep longer if it hasn't
// received any events recently)
}
}
Answering my own question here:
The reason for this problem was not down to detecting whether the parent process had died. In processEvents() I was polling the pipe from the parent process to see if there was any communication. When the parent died, poll() returned a value of 1 and the read loop thought there was infinite data waiting to be read.
The solution was to detect whether the pipe had been disconnected or not.

Emulating pipes

I've just recently learned about pipes and I would like to emulate the "|" gimmick provided by shells.
In the code below, the parent process spawns 2 child processes, after which they do their piping and get replaced by ls and grep. While that happens the parent process waits patiently. The problem is that the child processes never finish although they manage to send some data though the pipe and onto the screen.
There are other posts regarding pipes on SO, but I've never seen the setup in which the parent process launches 2 children. I've only seen the parent communicating with one child.
int p0[2];
pipe(p0); //creating pipe
if(fork() == 0) { //child 1
dup2(p0[0], STDIN_FILENO);
close(p0[0]); close(p0[1]);
execlp("grep","grep","a",NULL);
}
else { //parent
if(fork() == 0) { //child 2
dup2(p0[1], STDOUT_FILENO);
close(p0[0]); close(p0[1]);
execlp("ls","ls",NULL);
}
else { //parent
wait(NULL);
wait(NULL); //waiting for c1 and c2
close(p0[0]); close(p0[1]);
printf("parent exit\n");
}
}
My questions are: Why don't the child processes finish? Is fork-pipe structure sound or am I doing it completely wrong?
Close the pipe before starting to wait in the last section.

Resources