I've reduced the problem as much as I could to the following minimal code snippets. If more info is needed please ask.
Lets say I have a Java class called A whose main method is this:
public static void main (String args[])throws Exception{
Process p = new ProcessBuilder(args).redirectErrorStream(true).start();
Scanner in = new Scanner(new InputStreamReader(p.getInputStream()));
System.out.println(in.nextLine());
}
Basically, it runs a program from the terminal, reads in a line from that program, and echos it. Very simple.
Now I have a second program written in c++ like this:
int main()
{
string s;
cout << "example2 in c++"<<endl;;
cin >> s;
return 0;
}
When I invoke:
java A pathToC++Program
the program runs as expected, outputting the string sent from the cpp program and terminating.
I have an equivalent program in c:
int main()
{
char s[10];
printf("example1 in c\n");
fgets(s,10,stdin);
return 0;
}
When I invoke:
java A pathToCprogram
the program halts, and nothing is printed out.
When I remove the fgets line from the c program so that it looks like this:
int main()
{
printf("example1 in c\n");
return 0;
}
then the Java program is able to recognize the line and print it out. Thus it would seem that fgets is the problematic line, yet when fgets was included, even the line before it didn't work.
What is going on here?
(I have no idea if this is a peculiarity of Java or C, so I included both tags.)
Writing to stdout
(which is where printf
will write its output) is by default line-buffered, meaning the buffer will be flushed on newline.
But that's the default when running directly from a terminal. If the output is not a terminal, then stdout
will be fully buffered, meaning it will only be flushed when you fill the buffer. Or to an explicit fflush(stdout)
call.
In your C++ program you do flush the output explicitly, by using std::endl
(it writes a newline and flushes the buffered output). In your C program there's no such flushing of the output buffer.
This is really very platform specific, but for POSIX platforms (like Linux or macOS) it's like described above. I think it's quite similar for Windows.
As for why it works when you remove the fgets
statement, it's probably because fgets
will block execution until end-of-file or some (newline-terminated) input have been read. Without the fgets
the program will exit immediately after printf
and that will lead to the stdout
buffer being flushed.