This question already has answers here:
"printf" doesn't print a string immediately [duplicate]
(2 answers)
Closed 5 years ago.
I wrote the following piece of code to simulate a callback. But this got stuck and not even prints "inside main". I tried this on my unix machine and also on online compiler but same behavior. Have I missed anything ?
#include <stdio.h>
#include <unistd.h>
void sleep_50sec()
{
printf("inside sleep_50sec");
sleep(50);
}
int main()
{
int i;
printf("inside main");
sleep(1);
for( i =0; i < 100;i++)
{ printf("Loop %d",i);
sleep_50sec();
}
return 0;
}
Output
root#xyz> ./a.out
Add \n when printing to stdout.
printf("inside main\n");
The reason a \n is needed is because printf flushes data to stdout after \n was reached.
You can print to stderr to see your data immediately, without using \n:
fprintf(stderr, "test");
By the way, when calling printf() output will be written to stdout. So printf(...) is the same as fprintf(stdout, ...)
You have to flush the stdout. It can be done by the '\n' character inside the format string or by the fflush command:
void sleep_50sec() {
printf("inside sleep_50sec");
fflush(stdout);
sleep(50);
}
The reason you're not seeing anything printed is because the crt (C runtime) buffers your outputs and will only output to the screen after K characters have been accumulated. One solution will be to use '\n' - this hints crt that a complete line has been written, and that it should print it to the screen. Another solution will be to implicitly flush stdout like in my example below:
#include <stdio.h>
#include <unistd.h>
void sleep_50sec()
{
printf("inside sleep_50sec");
fflush(stdout);
sleep(50);
}
int main()
{
int i;
printf("inside main");
fflush(stdout);
sleep(1);
for( i =0; i < 100;i++)
{ printf("Loop %d",i);
fflush(stdout);
sleep_50sec();
}
return 0;
}
Related
Here is my code:
#include <stdio.h>
#include <unistd.h>
int main() {
printf("hello");
sleep(1);
fflush(stdout);
printf("\rworld");
sleep(1);
fflush(stdout);
printf("\r! \n");
sleep(1);
return 0;
}
It displays "Hello" for a second, does nothing for another second, and then goes straight to "!" I have tried to change the sleep durations and a few other things but nothing has fixed it. What am I doing wrong?
Flush before sleep to insure timely display.
stdout buffering mechanisms are implementation defined. Yet fflush() will get the output done promptly.
int main(void) {
printf("hello");
fflush(stdout);
sleep(1);
printf("\rworld");
fflush(stdout);
sleep(1);
printf("\r! \n");
fflush(stdout);
sleep(1);
return 0;
}
I'm trying to solve some simple example of process synchronization; in this particular example I want three processes: one prints "A", another prints "B" and the last prints "C". I want to print "A" first, then "B" or "C" and again "A", "B" or "C". To be more clear I want an output pattern like "ABACACABACABABACA...."
Below there is my symple code, termination is not managed because this is just an example to understand how things work.
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
void semaphore_init (int* sw){
if (pipe(sw) == -1) {
printf ("Error\n");
exit (-1);
}
}
void semaphore_wait (int* sw){
char buffer;
if (read(sw[0],&buffer,1) != 1) {
printf ("Error\n");
exit (-1);
}
}
void semaphore_signal (int* sw){
if (write(sw[1],"X",1) != 1) {
printf ("Error\n");
exit (-1);
}
}
int s1[2];
int s2[2];
void childA();
void childB();
void childC();
int main(){
pid_t pid;
semaphore_init(s1);
semaphore_init(s2);
semaphore_signal(s1);
pid=fork();
if(pid==0) childA();
else{
pid=fork();
if (pid==0) childB();
else {
pid=fork();
if(pid==0) childC();
}
}
wait(NULL);
return 0;
}
void childA(){
while(1){
semaphore_wait(s1);
printf("A-");
semaphore_signal(s2);
}
exit(0);
}
void childB(){
while(1){
semaphore_wait(s2);
printf("B-");
semaphore_signal(s1);
}
exit(0);
}
void childC(){
while(1){
semaphore_wait(s2);
printf("C-");
semaphore_signal(s1);
}
exit(0);
}
I don't understand why the output of this code is something like:
A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-C-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-A-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B
If, instead, I put the "\n" after the char I get the right output.
Could someone, kindly, explain me the reason of that?
In many implementations, including Linux, stdout is line buffered. This means any printf characters are stored to a (memory) buffer until a newline is encountered or the line buffer fills or the stream is flushed. In the example code this results in each process writing to their own local buffer every time it gains the semaphore. So even though the sequencing is correct as you intended but because there are three seperate buffers the final output result is not as you expect. Each process eventually flushes their buffer to stdout but each of those buffers only contain the same letter repeatedly.
The solution is to either add a newline to the printf (as you have found) or to do an explicit fflush(stdout). Another alternative is to use stderr which is not buffered by default: e.g. fprintf(stderr, "A-");
I need to read output of a program that uses carriage returns (\r) to make its output.
I have an old utility with output like this:
#include <stdio.h>
#include <unistd.h>
int main() {
setvbuf(stdout, (char*)NULL,_IONBF, 0);
fprintf(stdout, "Start\n");
for (auto i = 0; i < 100; ++i) {
fprintf(stdout, "\r%2d", i);
usleep(100000);
}
fprintf(stdout, "\nEnd\n");
return 0;
}
So I execute it with popen from my program and I need to trace a progress:
#include <memory>
#include <stdio.h>
int main(int argc, char* argv[]) {
if (argc != 2) {
return -1;
}
std::unique_ptr<FILE, int(*)(FILE*)> filePtr( popen(argv[1], "r"), &pclose );
int c = fgetc(filePtr.get());
while (c != EOF); {
printf("%c", c);
c = fgetc(filePtr.get());
}
return 0;
}
This work fine only without \r in stdout. Does anybody know is it possible to execute a process and read all output even with carriaage return symbols?
The problem here is that the carriage-return '\r' isn't really anything special, it's how you handle it that makes it different.
A terminal program uses it to control cursor position, but that's only done inside the terminal program itself, it's not "built-in" in the '\r' character.
If you want to handle it in a special way then you need to create your program that way.
This question already has an answer here:
Flushing buffers in C
(1 answer)
Closed 3 years ago.
I am trying to simulate a race condition (is this a correct term?) in order to fix it with semaphores afterward.
I have a master.c process:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
int main()
{
for(int i = 0; i < 100; ++i)
{
if (fork() == 0)
{
char str[12];
sprintf(str, "%d", i%10);
execl("./slave", "slave", str, (char *)0);
}
}
return 0;
}
And a slave.c process which prints into a file:
#include <stdio.h>
#include <unistd.h>
int main(int argc, char *argv[])
{
FILE *p_file;
p_file = fopen("out.txt", "a");
for (int i = 0; i < 100; ++i)
{
usleep(100000); // I tried using this but it changes nothing
fprintf(p_file, "%s", argv[1]);
}
fprintf(p_file, "\n");
return 0;
}
The output file out.txt looks like this:
https://pastebin.com/nU6YsRsp
The order is "random", but no data is not corrupted for some reason. Why is that?
Because stdio uses buffered output by default when writing to a file, and everything you're printing in each process fits into a single buffer. The buffer doesn't get flushed until the process exits, and then it's written as a single write() call, which is small enough to be written atomically to the file.
Call fflush(p_file); after each fprintf() and you'll get more mixed up results. Or call setvbuf() to disable buffering.
I have a program where I need to communicate with another program on its standard input and output. I can use a pipe to send it input and redirect its output to a specified file to be read when it is done, and that works fine. I am not using pipe and dup2 because I would like my program to at least somewhat work on windows as well as linux.
My issue is that I want to use the pipes to stream data.
I tried the following snippet:
#include <stdio.h>
int main()
{
while (!feof(stdin)) {
int x;
scanf("%d", &x);
printf("%x ", x);
fflush(0);
}
return 0;
}
in conjunction with:
#include <unistd.h>
#include <stdio.h>
int main()
{
int x;
FILE *p = popen("./test > tmp.datafile", "w");
FILE *f = fopen("tmp.datafile", "r");
for (int i = 0; i < 100; ++i) {
fprintf(p, "%d", i);
sleep(1);
x = fgetc(f);
printf("%c ", x);
fflush(0);
}
fclose(f);
pclose(p);
return 0;
}
However no matter what I do, I just keep getting nulls out of the file. I suspect that perhaps there are concurrency issues, in that I try to read the file before the test executable finishes flushing it, however I am not sure how to fix this.
Is there a better way to communicate with a program via standard streams in c?
fgetc() won't read past EOF once EOF has been reached — which may happen on the very first read. Doing something like
if(feof(f)) {
clearerr(f);
sleep(1);
} else {
printf("%c ", x);
}
should sort-of solve the issue with a busy loop.
A better idea would be to wait for the file to change once EOF has been reached, but that would require system-specific calls.
Beware of another race condition: fopen may happen before the file has been created by the command started via popen.
while(!(f = fopen(..., "r"))
sleep(1);
It's another busy loop and overall not a good solution that should only be used if dup2() is not available.
One of the issues in your code is that you are not writing any white space to the input of p, because of which the scanf() call in ./test is waiting for the input to finish so that it could read the value. Because of which the stdout of ./test remains empty. Fix it by something like this:
fprintf(p, "%d\n", i);
Also, consider using unbuffered I/O functions inside the ./test program. printf is part of the buffered I/O family of functions and the output might not be written immediately to the file.
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
int main()
{
while (!feof(stdin)) {
int x;
char s;
scanf("%d", &x);
sprintf(&s, "%x", x);
write(STDOUT_FILENO, &s, 1);
fflush(stdout);
}
return 0;
}