Hello I am writing a c program which runs then waits for it to complete then executes an if condition. However after the child process completes it does not execute the rest of code in parent. Any advice would be great. Thanks
AA
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
#include <signal.h>
#include <string.h>
int main() {
int D, waitVal3, waitVal4;
D = fork();
if(D == 0)
{
execv("DD", 0);
}
if(D != 0)
{
printf("\nPid = %d Code AA: created proccess Pid = %d (code DD)\n", getpid(), D);
}
waitVal3 = (waitVal4);
//NEVER ENTERS THIS CONDITION
printf("WAIT VAL: %d", waitVal3);
if(waitVal3 == D)
{
printf("\nPid = %d Code AA: process Pid = %d terminated\n", getpid(), D);
}
return 0;
}
DD
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
#include <signal.h>
int main (int argc, char *argBB[]) {
int C3, waitVal, waitVal2, ps;
C3 = fork();
if(C3 != 0)
{
printf("\nPid = %d Code DD: created proccess Pid = %d (code CC)\n", getpid(), C3);
}
if( C3 == 0 )
{
execv("CC", 0);
printf("\nexecv failed\n");
exit(0);
}
if(C3 < 0)
{
printf("Fork failed");
exit(1);
}
ps = fork();
if(ps != 0)
{
printf("\nPid = %d Code DD: created proccess Pid = %d (code ps)\n", getpid(), ps);
}
if( ps == 0 )
{
char command[50];
strcpy(command, "ps -u username");
system(command);
exit(11);
kill(ps, SIGKILL);//KILL PROCCESS PS HERE
}
waitVal = wait(waitVal2);
if(waitVal == ps)
{
printf("\nPid= %d Code DD: process Pid = %d terminated\n", getpid(), ps);
printf("\nPid = %d Code DD: killing process Pid = %d\n", getpid(), C3);
kill(C3, SIGKILL);
printf("\nPid= %d Code DD: process Pid = %d terminated\n", getpid(), C3);
printf("\nPid = %d Code DD: terminating\n", getpid());
exit(7);
}
return 0;
}
You didn't call wait() and your execv() was incorrect...
... compare this with your version to check the differences...
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
#include <signal.h>
#include <string.h>
#include <string.h>
#include <sys/wait.h>
#include <errno.h>
int main() {
char *args[2] = {"DD", NULL};
int D, waitVal3, waitVal4, rc, waitStatus;
D = fork();
if ( D == -1 )
{
printf("fork failed\n");
exit(1);
}
if(D == 0)
{
// ORIG: execv("DD", args);
rc = execv("/some/path/to/DD", args);
printf("execv failed: errno: %d\n", errno);
exit(1);
}
if(D != 0)
{
printf("\nPid = %d Code AA: created proccess Pid = %d (code DD)\n", getpid(), D);
}
waitVal4 = wait(&waitStatus);
waitVal3 = (waitVal4);
//ORIGINALLY - NEVER ENTERS THIS CONDITION
printf("WAIT VAL: %d", waitVal3);
if(waitVal3 == D)
{
printf("\nPid = %d Code AA: process Pid = %d terminated\n", getpid(), D);
}
return 0;
}
I tried to come up with a solution using waitpid() instead of wait().
Why this didn't work?
int main() {
char *args[2] = {"DD", NULL};
int waitVal3, waitVal4, rc, waitStatus;
pid_t D;
D = fork();
if ( D == -1 )
{
printf("fork failed\n");
exit(1);
}
if(D == 0)
{
// ORIG: execv("DD", args);
if( execv("/home/ubuntu/workspace/C/DD", args) == -1 ){
printf("execv failed: errno: %d\n", errno);
exit(1);
}
if( waitpid( D, &waitStatus, 0 ) == -1 ){
printf("Error waiting child process.\n");
exit(1);
};
printf("\nPid = %d Code AA: process Pid = %d terminated\n", getpid(), D);
}
return 0;
}
Observation:
If I put the waitid() statement outside the child process, this works.
The following code worked:
if(D == 0)
{
// ORIG: execv("DD", args);
if( execv("/home/ubuntu/workspace/C/DD", args) == -1 ){
printf("execv failed: errno: %d\n", errno);
exit(1);
}
}
if( waitpid( D, &waitStatus, 0 ) == -1 ){
printf("Error waiting child process.\n");
exit(1);
};
printf("\nPid = %d Code AA: process Pid = %d terminated\n", getpid(), D);
This means that the parent process was able detect the termination of child process in this case. My understanding is that waitpid() should work whether
in child or parent process. I am firm believer that it did work. However, the consequent printf() statement in the child process didn't get executed since the child process got terminated.
Related
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;
}
I have the following code with output:
#include <stdio.h>
#include <errno.h>
#include <unistd.h>
#include <string.h>
#include <wait.h>
#define PIPE_STDIN 0
#define PIPE_STDOUT 1
#define msg "hello world"
int main()
{
int fd_pipe[2];
int ret = fork();
if (ret < 0)
{
printf("Failed to fork\n");
return -1;
}
else if (ret == 0)
{
printf("Parent with PID %d\n", getpid()); fflush(stdout);
//sleep(3);
ret = write(fd_pipe[PIPE_STDOUT], msg, sizeof(msg)); fflush(stdout);
printf("Parent wrote string %d\n", ret); fflush(stdout);
wait( NULL );
printf("Parent done wait\n"); fflush(stdout);
}
else
{
char buf[80];
printf("Child with PID %d whose parent PID %d\n", getpid(), ret); fflush(stdout);
ret = read(fd_pipe[PIPE_STDIN], buf, sizeof(msg));
printf("Child read %s %d\n", buf, ret); fflush(stdout);
}
}
Output:
Child with PID 1130 whose parent PID 1131
Child read -1
Parent with PID 1131
hello world Parent wrote string 12
Parent done wait
From the output, why would child failed to read from pipe (returned -1) and then later on message "hello world" was printed ? Please explain the execution order that gives the above log.
You should call pipe before fork to init file descriptor.
fork() == 0 means child process.
The follow code could work:
#include <stdio.h>
#include <errno.h>
#include <unistd.h>
#include <string.h>
#include <wait.h>
#define PIPE_STDIN 0
#define PIPE_STDOUT 1
#define msg "hello world"
int main()
{
int fd_pipe[2];
int ret;
if (pipe(fd_pipe) == -1) {
perror("pipe");
return -1;
}
ret = fork();
if (ret < 0)
{
printf("Failed to fork\n");
return -1;
}
else if (ret != 0)
{
printf("Parent with PID %d\n", getpid()); fflush(stdout);
//sleep(3);
ret = write(fd_pipe[PIPE_STDOUT], msg, sizeof(msg)); fflush(stdout);
printf("Parent wrote string %d\n", ret); fflush(stdout);
wait( NULL );
printf("Parent done wait\n"); fflush(stdout);
}
else
{
char buf[80];
printf("Child with PID %d whose parent PID %d\n", getpid(), getppid()); fflush(stdout);
ret = read(fd_pipe[PIPE_STDIN], buf, sizeof(msg));
printf("Child read %s %d\n", buf, ret); fflush(stdout);
}
}
I am trying to understand fork, sleep... commmands.
I want to do 4 children and one parent operation exactly in this order. Parent> child1> child4> child2> child3.
The tasks of these processes are as I wrote in the code below. In this code I have 1 parent, 3 child and 1 grandson(child4 is a grandson). How can I make transactions in this order? I tried to put a sleep on each if's but the program finished without waiting for input in child2.
#include <sys/types.h>
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <sys/wait.h>
#include <stdlib.h>
int main(void)
{
int n1 = fork();
int n2 = fork();
int input;
if (n1 > 0 && n2 > 0) {
int n3=fork();
if(n3==0)
{ //3th child
printf("3th child process id is %d (parent: %d) \n", getpid(),getppid());
if(input == getppid()) {
printf("matched!\n"); }
else {
printf("not matched!\n"); }
printf("program ended\n");
}
else {
printf("parent process id is %d (parent: %d)\n", getpid(),getppid());
sleep(1);
}
}
else if (n1 == 0 && n2 > 0)
{
printf("1th child process id is %d (parent: %d)\n",getpid(),getppid());
FILE * fp;
fp = fopen ("xx.txt", "w+");
printf("file was created...\n");
sleep(1);
}
else if (n1 > 0 && n2 == 0)
{
printf("2th child process id is %d (parent: %d) \n", getpid(),getppid());
printf("Enter a key: \n");
scanf("%d",&input);
FILE * fp;
fp = fopen ("xx.txt", "w+");
fprintf(fp, "%d", input);
printf("input has been written to the txt file!\n");
}
else {
//4th child
printf("4th child grandson process id is %d (parent: %d)\n", getpid(),getppid());
printf("say me password!\n");
}
return (0);
}
You could try something like:
#include <sys/types.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/wait.h>
#include <stdlib.h>
int main(void)
{
const size_t nb_child = 3;
size_t children_count = nb_child;
while (children_count > 0) {
int pid = fork();
if (pid == 0) {
printf("child process id is %d (parent: %d) \n", getpid(),getppid());
if (children_count == 1) {
int pid2 = fork();
if (pid2 == 0) {
printf("child process id is %d (parent: %d) \n", getpid(),getppid());
sleep(2);
} else
wait(NULL);
}
return 0;
} else {
//father
}
children_count--;
}
while (children_count != nb_child) {
wait(NULL);
children_count++;
}
return 0;
}
The "difficult" part is to wait for all children before exiting
I'm trying to create n = 10 child processes and make its execute a peace of code ..
However it creates 14 child processes indifferent of n.
Why is that?
This is the sample code :
#include <stdlib.h>
#include <stdio.h>
int main()
{
printf("It worked! ");
return 0;
}
And this is the main program:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <unistd.h>
#include <sys/wait.h>
int main (int argc, char *argv[])
{
int n = 10;
pid_t pid;
int status = 0;
int fd2[2];
int i = 0;
while (i < n)
{
/*create the pipe */
if (pipe(fd2) == -1)
{
fprintf(stderr, "Problem at pipe: %s\n", strerror(errno));
exit(1);
}
/*create fork*/
pid = fork();
if (pid == -1)
{
fprintf(stderr, "Problem at fork: %s\n", strerror(errno));
exit(1);
}
else if (pid == 0) /*in child*/
{
close(fd2[0]);
close(1);
dup2(fd2[1], 1);
close(fd2[1]);
execl("sample.bin", "sample.bin", NULL);
fprintf(stderr, "Problem at exec: %s", strerror(errno));
exit(1);
}
/* in parent */
close(fd2[1]);
char line[255];
if (n = read(fd2[0], line, 254))
{
printf("%d The message is: %s\n", i, line);
}
close(fd2[0]);
wait(&status);
i++;
}
return 0;
}
I corrected the code, now the output is what I've expected. And of course another problem was that I used at read the same variable n.
I modified from this:
if (n = read(fd2[0], line, 254))
{
printf("%d The message is: %s\n", i, line);
}
To this:
int m;
while((m = read(fd2[0], line, 254) > 0)
{
printf("%d The message is: %s\n", i, line);
}
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
useconds_t BEAUTY_SLEEP = 500;
int main() {
int remains = 0;
char whoami[50];
pid_t pid;
pid_t ppid;
printf("%d\n", pid); //debug
printf("%d\n", getppid()); //debug
fflush(stdout); //debug
while (1) {
if ((ppid = getppid()) == 2704 && (pid == 0)) {
pid = fork();
if (pid == -1) {
perror("fork()");
exit(1);
}
printf("%ld\n", (long)ppid);
puts("beep");
} else {
usleep(BEAUTY_SLEEP);
}
}
return 0;
}
When I comment out "pid = fork()" in the while loop above, printf("%d\n", pid) prints the proper default value, 0. However, when I restore the pid = fork() line, the print statement outputs a non-zero process ID. Any clue as to why the retroactive assignment is happening?