FIFO read by Octave does not block as desired

classic Classic list List threaded Threaded
2 messages Options
Reply | Threaded
Open this post in threaded view
|

FIFO read by Octave does not block as desired

Marco Bravi-3
Dear Octave users,

        I would like to use Octave as the control environment for a
simulation environment, and the two should communicate over two FIFOs.

I am experiencing a misbehaviour of this type: once the input FIFO has
been read once (blocking read, as expected), all subsequent reads return
immediately, even if the other program is not blocked in the corresponding
write. No data is actually input by this read.

This is the infinite loop I use on the Octave part:

fid1 = -1;
fid2 = -1;


times = 10;

while (times)
     times--;
     if (fid1 < 0)
        fprintf(stderr, "Open gPROMS.pipe...");
        fid1 = fopen("../gproms/gPROMS.pipe", "r");
        fprintf(stderr, "done.\n");
     end
     fprintf(stderr, "I am about to read...");
     [a, b, c, d, e, f] = fscanf(fid1, "%g %g %g %g %g %g\n", "C")
     fprintf(stderr, "done.\n");
     fprintf(stderr, "Going to sleep...");
     sleep(15);
     fprintf(stderr, "awaken.\n");
     if (fid2 < 0)
        fprintf(stderr, "Opening Matlab.pipe...");
        fid2 = fopen("../gproms/Matlab.pipe", "w+");
        fprintf(stderr, "done.\n");
     end
     fprintf(stderr, "About to send Wf...");
     fwrite(fid2, "4\n");
     fflush(fid2);
     fprintf(stderr, "done.\n");
endwhile

The other side has been implemented in several ways. For test purposes, a
small C program using stdin/stdout and talking to the FIFOS is what I use
for debugging all my programs uising FIFOS.

What's most puzzling, is that once the first read has been performed
correctly (i. e., with blocking behaviour) the fscanf call returns *even
if the other program is terminated*, i. e., no other program is writing
the FIFO. This appears rather strange to me since I did not open the FIFO
for read/write (as it is often seen in order to avoid blocking on open).

Could you please suggest an explanation for this and a workaround for
correctly syncyng the two concurrent processes with this FIFO read/write
system?

Thanks a lot in advance.

        Marco Bravi

PS I am using Octave 2.0.13.

--
Marco Bravi [hidden email]
Dip. Ing. Chimica tel. +39-6-44585587 / 612
v. Eudossiana, 18 fax  +39-6-4827453
I-00184 Roma (Italy)





Reply | Threaded
Open this post in threaded view
|

FIFO read by Octave does not block as desired

John W. Eaton-6
On 28-Aug-1998, Marco Bravi <[hidden email]> wrote:

| I would like to use Octave as the control environment for a
| simulation environment, and the two should communicate over two FIFOs.
|
| I am experiencing a misbehaviour of this type: once the input FIFO has
| been read once (blocking read, as expected), all subsequent reads return
| immediately, even if the other program is not blocked in the corresponding
| write. No data is actually input by this read.
|
| This is the infinite loop I use on the Octave part:
|
| fid1 = -1;
| fid2 = -1;
|
|
| times = 10;
|
| while (times)
|      times--;
|      if (fid1 < 0)
|         fprintf(stderr, "Open gPROMS.pipe...");
|         fid1 = fopen("../gproms/gPROMS.pipe", "r");
|         fprintf(stderr, "done.\n");
|      end
|      fprintf(stderr, "I am about to read...");
|      [a, b, c, d, e, f] = fscanf(fid1, "%g %g %g %g %g %g\n", "C")
|      fprintf(stderr, "done.\n");
|      fprintf(stderr, "Going to sleep...");
|      sleep(15);
|      fprintf(stderr, "awaken.\n");
|      if (fid2 < 0)
|         fprintf(stderr, "Opening Matlab.pipe...");
|         fid2 = fopen("../gproms/Matlab.pipe", "w+");
|         fprintf(stderr, "done.\n");
|      end
|      fprintf(stderr, "About to send Wf...");
|      fwrite(fid2, "4\n");
|      fflush(fid2);
|      fprintf(stderr, "done.\n");
| endwhile
|
| The other side has been implemented in several ways. For test purposes, a
| small C program using stdin/stdout and talking to the FIFOS is what I use
| for debugging all my programs uising FIFOS.
|
| What's most puzzling, is that once the first read has been performed
| correctly (i. e., with blocking behaviour) the fscanf call returns *even
| if the other program is terminated*, i. e., no other program is writing
| the FIFO. This appears rather strange to me since I did not open the FIFO
| for read/write (as it is often seen in order to avoid blocking on open).
|
| Could you please suggest an explanation for this and a workaround for
| correctly syncyng the two concurrent processes with this FIFO read/write
| system?

What does the other process do in between writes to the FIFO?  Does it
exit or close the FIFO and then open it again before the next write?

I believe the behavior you are seeing is correct, but I can't be
absolutely sure, since you haven't provided all the details.

If you open a FIFO for reading only (i.e., mode == "r"), and no other
process has the FIFO open for writing, the open blocks.  Then once
another process opens the FIFO for writing, the reader of the FIFO
will be able to read from its end until the number of processes that
have the FIFO open for writing drops to 0.

If you open a FIFO for reading and writing (i.e., mode == "r+"), and
no other process has the FIFO open for writing, the open doesn't
block, but reading will.  Then your FIFO will stay open until you
close it, even if there are no writers on the other end.

I tried this with Octave 2.0.13 on a Linux system using the following
script:

  fid = -1;
  times = 10;

  mode = "r";  # or "r+", to keep the FIFO open even if no other
               # process is writing to it

  while (times)
    times--;
    if (fid < 0)
      fprintf(stderr, "Open foo.pipe...");
      fid = fopen("foo.pipe", mode);
      fprintf(stderr, "done.\n");
    endif
    fprintf(stderr, "I am about to read...");
    s = fgetl(fid);
    fprintf(stderr, "done.\n");
    if (isstr (s))
      fprintf (stderr, "read: %s\n", s);
    else
      fprintf (stderr, "read on pipe failed\n");
    endif
    fprintf (stderr, "sleeping...");
    sleep (1);
    fprintf (stderr, "done\n");
  endwhile

Running this script with mode = "r" when no other processes have the
FIFO open for writing results in the open blocking.  Then when another
process opens the FIFO and starts writing, the script echos data
returned by the call to fgetl.  If there are fewer than 10 writes
before the other process exits, fgetl sees EOF on the FIFO and quits
reading.  Even if another process later opens the FIFO for writing,
Octave will still see EOF unless it closes and reopens the FIFO.

Running this script with mode = "r+" when no other processes have the
FIFO open for writing causes Octave to *not* block at the open, but
instead to block at the first call to fgetl.  Then when another
process opens the FIFO and starts writing, the script echos data
returned by the call to fgetl.  If there are fewer than 10 writes
before the other process exits, fgetl blocks until another process
writes to the FIFO.

In my tests, I just used

  echo foo > foo.pipe

or

  for i in 0 1 2 3 4 ; do echo $i ; done > foo.pipe

to write to the FIFO.

Based on what I've just read about FIFOs in "Advanced Programming in
the Unix Environment" by Stevens, I believe this is the correct
behavior, but please correct me if I'm getting something wrong here.

Thanks,

jwe