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)