[comp.sys.sgi] Nonflushing fclose

Tim_Buxton@UM.CC.UMICH.EDU (06/15/91)

Netlanders:
 
We are having serious intermittent problems as we *try* to communicate
between processes  using fscanf() and fprintf().  We had used
pipes previously, with success.  When we added signal handling
to the processes however, the pipes "broke", and according to the
documentation, this is Just the Way It Is; pipes become nonblocking
when signals are used.  Writing to/reading from a scratch file
seemed a logical alternative.
 
Our problem seems to happen because the system INSISTS on
writebehind buffering with fprintf(), and the fscanf() just
plows ahead and tries to read junk when the fprintf() output
is delayed by other traffic on the system.  The only way
we have found to fix the problem is to put a sleep() command
in to (maybe) insure the system has time to flush its buffer.
This is clearly unreliable, however.  Has anyone found a
workaroud to this problem?
 
The code works (roughly) as follows:
 
 PROCESS 1
 
       .
       .
       .
  fp=fopen("file"...
  fprintf(fp,"%s\n", stuff....
  fclose(fp); /* this does not flush the buffer before proceeding*/
  <send signal to process 2 that file is complete>
 
 
 PROCESS 2
 
       .
       .
       .
  <wakes up on signal from PROCESS 1>
  sleep(2);  /* this works but is wasteful and undependable */
  fp=fopen("file"...
  fscanf(fp,"%s", maybegarbage ); /* here the problem
                                  happens when garbage
                                  is read in sometimes */
 
/* end of pseudocode */
 
 
The Hotline has said yes, this is a problem, but that the low-level
open(fileid, O_SYNC|WRITEONLY); would *actually* flush the buffer
*before* sending the signal in PROCESS 1.  This will involve rewriting
substantial code, and I would appreciate hearing about easier workarounds
that others have found.  Whatever we find to be easiest, I will
summarize to the net once we prove it works.  Thanks.
 
                         Tim Buxton
                         OptiMetrics, Inc.
                         Tim_Buxton@um.cc.umich.edu
 
 

blythe@sgi.com (David R. Blythe) (06/17/91)

In article <8810253@um.cc.umich.edu> Tim_Buxton@UM.CC.UMICH.EDU writes:
>Netlanders:
> 
>We are having serious intermittent problems as we *try* to communicate
>between processes  using fscanf() and fprintf().  We had used
>pipes previously, with success.  When we added signal handling
>to the processes however, the pipes "broke", and according to the
>documentation, this is Just the Way It Is; pipes become nonblocking
>when signals are used.  Writing to/reading from a scratch file
>seemed a logical alternative.

I'm not sure I agree.  using select() or a simple read() loop until you
encounter the record delimiter (i.e. '\n') on the read end would work
fine with pipes, sockets, etc ...  Then pass the accumulated buffer to
sscanf().
	david blythe

jwag@moose.asd.sgi.com (Chris Wagner) (06/18/91)

In article <8810253@um.cc.umich.edu>, Tim_Buxton@UM.CC.UMICH.EDU writes:
|> Netlanders:
|>  
|> We are having serious intermittent problems as we *try* to communicate
|> between processes  using fscanf() and fprintf().  We had used
|> pipes previously, with success.  When we added signal handling
|> to the processes however, the pipes "broke", and according to the
|> documentation, this is Just the Way It Is; pipes become nonblocking
|> when signals are used.  Writing to/reading from a scratch file
|> seemed a logical alternative.
|>  
|> Our problem seems to happen because the system INSISTS on
|> writebehind buffering with fprintf(), and the fscanf() just
|> plows ahead and tries to read junk when the fprintf() output
|> is delayed by other traffic on the system.  The only way
|> we have found to fix the problem is to put a sleep() command
|> in to (maybe) insure the system has time to flush its buffer.
|> This is clearly unreliable, however.  Has anyone found a
|> workaroud to this problem?
|>  
|> The code works (roughly) as follows:
|>  
|>  PROCESS 1
|>  
|>        .
|>        .
|>        .
|>   fp=fopen("file"...
|>   fprintf(fp,"%s\n", stuff....
|>   fclose(fp); /* this does not flush the buffer before proceeding*/
|>   <send signal to process 2 that file is complete>
|>  
|>  
|>  PROCESS 2
|>  
|>        .
|>        .
|>        .
|>   <wakes up on signal from PROCESS 1>
|>   sleep(2);  /* this works but is wasteful and undependable */
|>   fp=fopen("file"...
|>   fscanf(fp,"%s", maybegarbage ); /* here the problem
|>                                   happens when garbage
|>                                   is read in sometimes */
|>  
|> /* end of pseudocode */
|>  
|>  
|> The Hotline has said yes, this is a problem, but that the low-level
|> open(fileid, O_SYNC|WRITEONLY); would *actually* flush the buffer
|> *before* sending the signal in PROCESS 1.  This will involve rewriting
|> substantial code, and I would appreciate hearing about easier workarounds
|> that others have found.  Whatever we find to be easiest, I will
|> summarize to the net once we prove it works.  Thanks.
|>  
|>                          Tim Buxton
|>                          OptiMetrics, Inc.
|>                          Tim_Buxton@um.cc.umich.edu
|>  
|>  

-- 
I am a bit confused - a call to read a pipe can be interrupted
by a signal, but the read will return EINTR - you could just loop
and read again. The problem comes in using fscanf - the stdio
library isn;t so could about getting interrupts.
You could switch to doing your own read/write(2) system calls, then
calling sscanf and sprintf to do the formatting.

As for fflush/fclose - it definetly flushes out all write-behind data
from the user process into the system, where any read will find it.
Doing O_SYNC is defintely NOT the right answer! this synchrously
writes stuff to disk - there is no reason for this.

If you aren;t worried about getting signals during the read
(which you appearently are not since you are willing to
switch to a temp file), then you could also simply go back
to pipes and fprintf/scanf and simply put is sighold(3) around those
to temporarily block signals.

----
Chris Wagner (jwag@sgi.com)