Question

All program on xinetd (which I've read) call fflush(). Why?

For example, Inetd-Wikipedia

#include <stdio.h>
#include <stdlib.h>

int main(int argc, char **argv)
{
  const char *fn = argv[1];
  FILE *fp = fopen(fn, "a+");

  if(fp == NULL) 
    exit(EXIT_FAILURE);

  char str[4096];
  //inetd passes its information to us in stdin.
  while(fgets(str, sizeof(str), stdin)) {
    fputs(str, fp);
    fflush(fp);
  }
  fclose(fp);
  return 0;
}
Was it helpful?

Solution

fopen uses buffered input. That is to say that calling fputs will write to the in-memory buffer and will not necessary write the data to disk. Calling fflush forces the output buffer to be written to disk.

Your sample code is using this pattern so that the file will be written as soon as some data is written over the socket, and you can monitor the file to know what was written.

OTHER TIPS

I don't think you ever need to call fflush just before fclose. I don't see any reason to call fflush after each fputs. Basically you only need fflush when you need to synchronize some actions but in most cases there are better ways to do that. You should IMO generally avoid fflush unless you're a database developer or something along that line.

If you remove the fflush, the program will work just as well, i.e. will dump stdin to a file and will close the file upon exit.

Also, I don't think it has anything to do with inetd or xinetd.

As writen in another answer, monitoring the file will only show data immediately if the buffers are flushed, but I think it is a bad programming practice to flush after each read. If you want to always get the data immediately, it's better to use:

setvbuf(fp, NULL, _IONBF, 0)

But even that's not enough as the buffering of stdin which is the source of your data is AFAIK not specified. You would need to set that as well:

setvbuf(stdin, NULL, _IONBF, 0)

I believe that you should always prefer POSIX functions over ANSI functions if you want to control the read/write behavior precisely and you don't target non-POSIX platforms. The semantics of POSIX open(), read() and write() is much simpler than the one of fopen(), fread() and fwrite(). It simply reads/writes as much data as possible in one system call and there's no buffering except your own buffer and the kernel socket buffer which just gives you data whenever you ask for it.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top