Printf before fork() is being printed twice [duplicate] - c

This question already has answers here:
printf anomaly after "fork()"
(3 answers)
Closed 7 years ago.
I was writing a multi-process program using fork() and i bumped into a problem.
Below is a sample code reproducing the problem (without any sort of error checking):
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
int main() {
printf("hello world");
fork();
}
This code prints 2 "hello world" statements (one from parent and the other from child). However this should not be the case since the printffunction call is prior to the fork() system call.
After testing, the problem appears to be solved by the following:
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
int main() {
printf("hello world\n"); \\ addition of the new line character
// or by using fflush(stdout);
fork();
}
My guessing is that the printf buffer is being copied while its not flushed, so the child process is emptying its copy of this buffer before exiting. Hence the other printf shows.
Can anyone provide a better explanation of this issue? Or even better, correct me if i am wrong or missing something.

The file handle stdout (which is used by printf) is by default line buffered, which means output using printf will be flushed (and shown in the console) either when there's a newline or when the buffer is full.
As fork creates an exact duplicate of the parent process, both processes have the same contents in the (un-flushed) output buffer, and both will be flushed when the two processes exits.
So yes you're correct in your guessing.

Related

execl in C programming

I have a C program. I noticed that you can't put 2 execl's in it.
The code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>
int main()
{
pid_t fork(void);
int system(const char *command);
execl("/bin/sh", "sh", "-c", "kdialog --warningcontinuecancel
\"Make sure to include: \n \n 1. py_lcd folder \n 2. 4x20
Raspberry Pi LCD Display \n 3. Python 2.7.12 to be installed \n
\n If you are missing something, kill the program process and
get them.\"", (char *) 0);
sleep(1);
execl("/bin/sh", "sh", "-c", "kdialog --msgbox \"Setting up files...\" --title \"Installing...\"", (char *) 0);
return(0);
}
Can someone help me if there is a way to bypass this or if i am making a mistake???
The exec family of functions don't return when they succeed. They replace the running process with the one being execed. If you want to run a program in a child process (with full control, unlike system), you need to use fork + exec + wait (or perhaps posix_spawn).
Anything written after execl is a deadcode. The main purpose of execl is to re-use the current process information for a new process to improve performance. You will be using sharing the same structures of process information(pid, stack, heap etc.) of the current process where execl is executed.
I found an answer myself. There is a system() command which works the exact same but you are able to insert it anywhere in the code without problems

Segmentation fault using execvp in c shell [duplicate]

This question already has answers here:
C - Executing Bash Commands with Execvp
(3 answers)
Closed 6 years ago.
#include <stdio.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
void main(){
char *cmd;
pid_t pid;
while (1) {
printf("$ ");
fgets(cmd,1000,stdin);
if (pid = fork() == -1) {
exit(1);
}
else if (pid == 0){
execvp(cmd,&cmd);
}
else{
int status;
wait(&status);
}
}
}
I am making a simple shell that executes commands but when I enter the command at the prompt I keep getting segmentation fault. This is the most simple version that only works for one-argument commands like "ls"
For your problem, in your code,
fgets(cmd,1000,stdin);
cmd is uninitialized. It does not point to a valid memory. Accessing invalid memory invokes undefined behavior.
You need to allocate memory to cmd before you ca use that. Alternatively, you can consider making cmd an array, like char cmd[1000] = {0}; to avoid the need to allocate memory yourself.
Then, execvp(cmd,&cmd); is not quite right, it's not what you think it is. Read the man page for a better understanding.
That said, for a hosted environment, void main() should at least be int main(void) to have standard conformance.

open doesn't return error when file is currently opened in a running process

This is my code. I'm completely aware that an endless loop results when executing directly. What I did was I compiled this code and then executed twice in the linux command line via ./a.out & twice. The first time the program executes, it runs fine and gives a decent file handle. When the first instance of the program is running in the background and I execute the second instance one minute later (via ./a.out &), the file handle returned is the exact same. I was expecting a negative return value for the second instance to indicate the first instance is using the file.
How do I solve this issue? I don't want to use buffered file functions like fopen/fread because the file I want to make is small and must be made at the beginning of the program before anything else happens in the code.
This is my code:
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int main(){
char* pidf="/testpid.del";
int lfp=open(pidf,O_WRONLY|O_CREAT|0x700);
printf("File handle = %d\n",lfp);
if (lfp ==-1){printf("Can't use PID file: %s\n",pidf);return -1;}
while(1){
sleep(1);
}
close(lfp);
}

Output of this fork() program [duplicate]

This question already has answers here:
Working of fork() in linux gcc [duplicate]
(5 answers)
Closed 10 years ago.
#include<stdio.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<errno.h>
int main()
{
printf("abcd");
fork ();
printf("pqrs\n");
return 0;
}
This program gives the output as follows:
abcdpqrs
abcdpqrs
But how is it possible? Shouldn't it be:
abcdpqrs
pqrs
No
it's because fork also copies the datastructure used in printf, holding the buffer to be printed out.
If you fork the program, the buffer is not flushed.
printf does not necessarily flush stdout immediately, so what happens is that "abcd" is buffered until next output is executed. Since later both "sides" of the fork do the output, both will also flush out the "abcd".
To make it work the way you're probably guessing it would, try flushing manually;
int main()
{
printf("abcd");
fflush(stdout);
fork ();
printf("pqrs\n");
return 0;
}
$ ./a.out
abcdpqrs
pqrs

fork() and stderr with terminal

I use fork() in order to make different proccesses running and printing a simple message.The result of the code counfuses me though.. Take a look at the code:
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <math.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <time.h>
int main(void)
{
fork();
fork();
fork();
fprintf(stderr,"hello world\n");
}
and the output is:
mario#ubuntu:~/OS$ ./main
hello world
hello world
hello world
hello world
hello world
hello world
mario#ubuntu:~/OS$ hello world
hello world
mario#ubuntu:~/OS$
Note that i execute the program at the first line of the terminal but the output is not what i expected. Please help me! Thanks in advance! Same things happen if fprintf is changed with printf("......")
EDIT:I cant understand why the prints are this way. Six before the terminal line one next to it and 1 after it...
When the parent program exited, the shell running the parent program printed the shell prompt mario#ubuntu:~/OS$ on the screen. Any child program which had not printed it's hello world by then would be printed after the prompt. If you want the prompt to not appear before all the hello worlds, you need to make the parent wait for all it's child and grandchild programs to terminate.
Check this to see how to make parent wait.
You are creating 8 processes. Each fork divides the process into two. It the original parent finishes the other processes my still be executing. Hence if the original process finishes executing the shell gets a go and prints the prompt despite the other processes are still executing.

Resources