What happens if I call fork() inside main? [duplicate] - c

This question already has answers here:
Working of fork() in linux gcc [duplicate]
(5 answers)
Closed 9 years ago.
Simple piece of code:
#include <stdio.h>
#include <string.h>
main()
{
printf("Process");
fork();
fork();
return 0;
}
From my understanding of fork(), after this code executes we will have 3 child processes and 1 parent process. Also whenever we call fork() the execution should start from the statement immediately after the fork() statement. Hence according to me "Process" should be printed only once. But in my output Process is being printed 4 times. How is that possible?

Because the standard output is line buffered by default, when you call fork(), the output buffer is inherited by all the children processes.
There are several different ways to change this behavior:
Add a new line character at the end:
printf("Process\n");
or call fflush() to flush the output:
printf("Process");
fflush(stdout);
or change standard output to not buffered using setbuf() or setvbuf():
setbuf(stdout, NULL);
printf("Process");
Using either way, you'll see the output only once.
Note: see #Dvaid Schwartz's answer for the bug with calling atexit() multiple times in your code.

Your program has a bug. All the children return from main, causing atexit handlers to run four times. The children should call _exit.
Here's how your code should look:
#include <stdio.h>
#include <string.h>
#include <unistd.h>
main()
{
int is_child = 0;
printf("Process");
if (fork() == 0)
is_child = 1;
if (fork() == 0)
is_child = 1;
if (is_child)
_exit(0);
return 0;
}

Related

Unexpected output on a fork call in C [duplicate]

This question already has answers here:
Why is main called twice?
(3 answers)
Closed 1 year ago.
I encountered this in my school work and it didn't produce what I thought it should:
int main() {
printf("c");
fork();
printf("d");
}
I know there are several things that aren't good about this code (i.e. no parameters in main, no variable for the return value from fork, no return statement at the end, etc.), but this is how it was presented and it's not relevant to my question anyway.
This code produces the output:
cdcd
It was my understanding that when fork is called, both parent and child would resume/begin on the line after the fork call. Based on that, I would have expected the output to be:
cdd
Assuming, of course, that the fork call is successful. Can anyone explain to me why that "c" is printed a second time even though it's on the line before the fork call?
Thanks!
M_MN
You forked your program before flushing stdout (i.e.: data was still in the output buffer). Just call fflush(stdout) to fix it:
❯ cat test.c
#include <stdio.h>
#include <unistd.h>
int main() {
printf("c");
fflush(stdout);
fork();
printf("d");
}
[22:14:01]~/devel
❯ clang test.c -o test
[22:14:07]~/devel
❯ ./test
cdd[22:14:09]~/devel
The reason you're seeing c twice is that the fork() duplicates the unprinted buffered output. You could flush the output stream before the fork():
fflush(stdout);
Or you could set stdout to be unbuffered, but you should do this first, before calling printf() the first time:
setvbuf(stdout, NULL, _IONBF, 0);
Here's what I'm guessing is happening. printf writes to the stream stdout. Since you didn't flush stdout after printing "c" nor did that string end in a new line, the character sat there in a user-space buffer. When you called fork, the child process got a copy of the parent's virtual address space including the buffered text. When both programs exited, their buffers were flushed and so "c" showed up twice.
Try adding fflush(stdout); just prior to the call to fork.

Returning string from C system() function [duplicate]

This question already has an answer here:
Getting output of a system command from stdout in C
(1 answer)
Closed 4 years ago.
I just learned C and fascinates with pointers. Recently I discovered C function system(). I am able to get return values from a program I executed via system ("program.exe"). Eg, program.c:
#include <stdio.h>
int main(){
printf("hello world\n");
return 123;
}
and this code calls program.exe, called call.c
#include <stdio.h>
#include <stdlib.h>
int main(){
int a;
printf("calling program.exe:\n");
a=system("program.exe");
printf("program.exe returned %d at exit\n",a);
return 0;
}
When I execute call.exe, I get this
calling program.exe:
hello world
pm returned 123 at exit
I was like, wow! This return value and system() function thing is like a new way to interprocess communication for me. But my question is, can I get a string return from the system() function?
Ii tried changing program.c "int main()" to "char * main()", and return 123 to return "bohemian rhapsody" and change "int a;" to "char *a;", printf format %d to %s in call.c, but I only get funny characters when I execute call.exe. I wonder what's wrong?
No you can't return a string from system(), and indeed a program under most modern desktop operating systems can only "return" an integer exit code when it terminates.
If you do want to get a string back from the executed program, one way would be to use popen() to invoke the program, and then have that program write the string to stdout.
The program that you call 'call.c' calls system(3), which does the following,
suspends the current process,
starts a child process,
and waits for the child process to complete
The return value from the called process, 'program.c/exe' is an integer (size is system dependent usually 16-bit), and what is happening behind the scenes is that the system(3) call uses the wait(2) call to (blocking) suspend execution until the child process returns.
Note that the string is not returned, but the child process prints to stdout. See the popen(3) call if you want to obtain the string (or binary) output from the child process.
See the manual page for wait(3) to see how to process the results returned by the called program, e.g. 'man -s2 wait',
WAIT(2) System Calls Manual WAIT(2)
NAME
wait, wait3, wait4, waitpid -- wait for process termination
SYNOPSIS
#include <sys/wait.h>
pid_t
wait(int *stat_loc);
pid_t
wait3(int *stat_loc, int options, struct rusage *rusage);
pid_t
wait4(pid_t pid, int *stat_loc, int options, struct rusage *rusage);
pid_t
waitpid(pid_t pid, int *stat_loc, int options);

Where does fork() start from [duplicate]

This question already has answers here:
printf anomaly after "fork()"
(3 answers)
Closed 4 years ago.
So as far as i know fork creates a duplicate of the process it's called from but it also copy's it's program counter so it continues from the line after it's called but why is this code printing hello world twice when it's before the fork
#include <stdio.h>
#include <sys/wait.h>
int main()
{
printf("Hello World");
fork();
wait(NULL);
return 0;
}
printf doesn't actually print -- it actually just puts data into a buffer to be printed later. It will actually be printed when the buffer gets flushed, which can happen in a variety of ways.
In your case, the buffer flush doesn't happen until after the fork, so both the parent and the child have a copy of the string to be printed in the buffer when they fork, and both end up printing it.

C fork program behaviour explanation

I'm completly new to the C language and Unix systems. I might formulate myself badly or wrong. I have a C program where two processes increments a global variable up to 30. I am aware that order of output is random with parallel processing. But when using the | more pipe, the output is always the same: Child 1-30 -> Parent 1-30. How come?
I've been told that when using printf to print a variable, the variable content is sent to a buffer before printing to screen. And apparently you can use new line (\n) to flush the buffer right away. Is this information connected?
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
#include <sys/types.h>
int g_ant = 0;
void writeloop(char *text)
{
long i = 0;
while (g_ant < 30)
{
if (++i % 100000 == 0)
printf("%s: %d\n", text, ++g_ant);
}
}
int main(void)
{
pid_t pid;
pid = fork();
if (pid == 0)
{ /* child */
writeloop("Child");
exit(0);
}
writeloop("Parent"); /* parent */
waitpid(pid, NULL, 0);
return 0;
}
Your information is basically correct.
When the output goes to the terminal, the output is line buffered. When the output goes to a pipe, the output is fully buffered, so one of the processes finishes its output first. You could add fflush(stdout) after each iteration in writeloop(), or use setvbuf() to make it line buffered, or even unbuffered output.
Incidentally, note that the global variable is not shared between the child and the parent process; they each have their own copy of the variable.

Questions on fork() [duplicate]

This question already has answers here:
printf anomaly after "fork()"
(3 answers)
Closed 8 years ago.
I am trying to understand fork(), and so I put together the following example:
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
void main()
{
if(fork()==0)
{
printf("2");
if(fork()==0)
{
printf("4");
}
else
{
printf("3");
}
}
else
{
printf("1");
}
}
When I was tracing this on paper, I drew the following sketch:
So I believe the output should be 1234. However, when I run this code, the output is 12324. Why is that? Where is my mistake?
Update:
After reading the comments, it was suggested to do any of the following
Add \n to each printf statement
OR: Add fflush(stdout); after each printf statement
OR: Add setbuf(stdout, NULL); <---- this is what I ended-up doing :)
After updating my code, the output was indeed 1234.
printf() output is usually line-buffered. So when you fork(), the new processes gets the copy of the buffer as well. When the process exits, the whole buffer is flushed (or anytime it's flushed in the code or whenever the buffer becomes full). Hence, you see a copy of printf's output one more time.
1) You can flush it after each printf() call by using fflush(stdout);
2) or using \n for example:
printf("2\n");
Another way is to disable the buffering with:
setbuf(stdout, NULL);
Your analysis is almost correct. However, printf does not necessarily write immediately do file descriptor - output is buffered inside the process. The second process does fork after putting 2 in the buffer. Both second and third processes will have it in the buffer and print 2.
If you do printf("2\n") instead new line character will force printf to flush the buffer and you will see only one 2.

Resources