c - printf c issues in terminal - c

I have the following code in my main:
//testing with fork
printf("I am process: %d\n", getpid());
pid_t pid = fork();
printf("Now I am process: %d\n", getpid());
printf("fork returned %d\n", pid);
if(pid == 0){
printf("I am child %d\n", getpid());
}
However the output on my terminal gives me this:
terminal output pic
I run my program with a param of 'config_file.txt' as you can see on the first line, and the rest of it prints out fine until it hits the fork, and my cmd line comes up in between it...any ideas on why that is or how I can fix it? Is there something wrong with the code? I was just following a simple forking tutorial.
Edit: Also, after running it my program hangs there, and I have to hit enter to get my cmd line back up.

What's happening is that the parent process is finishing before the child process. When the parent finishes the prompt is displayed, however since the child is still running it continues to print output to the console.
If you want the parent to wait until the child is done, use the wait() function:
printf("I am process: %d\n", getpid());
pid_t pid = fork();
printf("Now I am process: %d\n", getpid());
printf("fork returned %d\n", pid);
if(pid == 0){
printf("I am child %d\n", getpid());
} else {
wait(NULL);
}

Related

Why child_1 will print before parent?

I have a C code that a parent process will fork() a child process:
int main(){
pid_t child_1;
child_1 = fork();
if (child_1 > 0){
printf("Parent: (PID %d)\n", getpid());
wait(NULL);
}
else if (child_1 == 0){
printf("child: %d", getpid());
}
}
And the output is:
Parent: (PID 1234)
child: 1235
But if I removed the \n in the printf of parent, the output would become:
child: 1235Parent: (PID 1234)
I'm not sure why and I've tried on different OS and the output is the same. Thanks in advance.
printf is line buffered. Which means it won't actually output until a newline is encountered or an explicit flush is done (such as when the process exits). So in your case removing the newline changes when the parent process actually outputs. Since the parent waits for the child to exit it means the parent flush will occur after the child has outputted.

Parent/Child process print

I'm writing a C program that creates a child process. After creating the child process, the parent process should ouput two messages: "I am the parent" then it should print "The parent is done". Same for child process "I am child" and "The child is done". However I want to make sure, the second message of the child is always done before the second message of the parent. How can I achieve to print "The child is done" and "The parent is done" rather than printing their pid?
#include <unistd.h>
#include <stdio.h>
main()
{
int pid, stat_loc;
printf("\nmy pid = %d\n", getpid());
pid = fork();
if (pid == -1)
perror("error in fork");
else if (pid ==0 )
{
printf("\nI am the child process, my pid = %d\n\n", getpid());
}
else
{
printf("\nI am the parent process, my pid = %d\n\n", getpid());
sleep(2);
}
printf("\nThe %d is done\n\n", getpid());
}
You could have a flag variable, that is set in the parent, but then the child clears it. Then simply check for that for the last output.
Something like
int is_parent = 1; // Important to create and initialize before the fork
pid = fork();
if (pid == -1) { ... }
if (pid == 0)
{
printf("\nI am the child process, my pid = %d\n\n", getpid());
in_parent = 0; // We're not in the parent anymore
}
else { ... }
printf("\nThe %s is done\n\n", is_parent ? "parent" : child");
Call wait(2) in the parent process for the child to complete.
else
{
wait(0);
printf("\nI am the parent process, my pid = %d\n\n", getpid());
}
You should check if wait() succeeds and main()'s return type should be int.

Tracing the execution of a process

I have this code that gets its process ID and its parent process:
#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
int main(){
int pid;
printf("I am the original process with PID %d and PPID %d. \n", getpid(), getppid());
pid = fork();
if (pid >0){
printf("I am the original process with PID %d and PPID %d \n", getpid(), getppid());
printf("My child’s pid is %d \n" , pid);
}
else if(pid == 0) {
printf ("I am the original process with PID %d and PPID %d \n", getpid(), getppid());
}
else if (pid == 1){
printf ("Error – no child process was created \n");
}else{
printf ("Error – system error \n");
}
printf (" PID %d terminates \n", getpid()); /* both processes execute this instruction */
return 0;
}
OUTPUT
I am the original process with PID 1009 and PPID 964.
I am the original process with PID 1009 and PPID 964
My child’s pid is 1010
PID 1009 terminates
I am the original process with PID 1010 and PPID 1009
PID 1010 terminates
Few questions that confuses me..
how does this code is executed?
In the output, you can see that it runs the code under under if(pid == 0) while the condition if(pid > 0) is already executed. how come pid is equal to 0? while it was set already to greater than 0.
Lastly , what does fork() really do?
fork() makes multiple processes, or a "child". So the parent and child execute the code. The parent's pid is > 0 and the child's is ==0.
So, the parent and child execute at similar times starting at the fork command. So let's start with the parent. The parent checks the first statement (pid > 0) and finds it is true, so it prints out the two statements. Then it goes all the way to the print statement after the last else.
Now to the child. The child checks the first if statement, and is false. Checks the next (pid == 0) and finds it is true. So now it's going to print out that statement. Now it will skip to the print statement after the else and prints again.
Note: The parent and child can execute at different times, so if you run the code multiple times the output may be in a different order.

Loading pid_t into an array for use OUTSIDE of forked process C/linux

I have have an application that forks quite a few child processes. I would like to store these child pid's in an array so when MAX_CHILD is reached. I can kill off the oldest ones.
Any way of accomplishing this ?
note... In my real application I fork and do not wait for process to finish
here is a test snippet...
---main
pid_t pid;
if ((pid = fork()) < 0) {
printf("[*]- ERROR -> Fork returned -1\n\n");
}
else if (pid == 0) {
// Success
// Child process begins here
printf("Inside Child # PID %i . Check ps\n", pid);
sleep(30);
}
else {
// Still good here
// Maybe store pid to global array here?
printf("Back to parent PID: %i CHILD: %i\n\n", getpid(), pid);
}
// pid comes out as 0 here as expected
printf("PID: %i\n", pid);
So I would like to store pid into a int array maybe? How do you correctly cast pid_t?
I want to be able to call a cleanup() function and have it step through a list of child PIDs to see if they are still active, if yes, then kill the oldest.
Any advice would be appreciated. Thank you.

How to detach a forked process from parent in 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/

Resources