-2

I am implementing a named pipe to write and read data between two processes in cpp. The first process acquires a feature point from an image in real time while the second reads this feature point. It works fine but after a couple of data exchanges between the two processes, the talker code freezes. I know I need to close a pipe in order to be able to read from it and when I tried to close the file descriptor in the talker code outside a while loop, the listener file could not access new values of the variable. I can't find a way around it at the moment. What could I possibly be missing?

Here's a MCVE of a function that writes a variable to a fifo file:

#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
#include <opencv2/opencv.hpp>

/*Function Prototypes*/
void(cv::Mat frame);    
int(talker);

 int talker(float depthright)
 {
   int fd;
   char depthstring[1024];    
   sprintf(depthstring, "%4.4f", depthright);

   char * myfifo = "/tmp/myfifo";

   mkfifo(myfifo, 0666);           /* create the FIFO (named pipe) */
   fd = open(myfifo, O_WRONLY/* | O_NONBLOCK*/);       
   write(fd, depthstring, sizeof(depthright) );    

   /* close FIFO and delete fifo names from file system */
   close(fd);
   unlink(myfifo); 

   return 0;
}

int main( int argc, char* argv[] )
{
 cv::Mat frame;
//convert frame to grayscale, equalize histogram of grayed frame
//detect faces and then detect eyes; acquire eye depth values as depthright
 talker(depthright);     //call fifo talker funtion
return 0;
 }

The listener is below:

int main()
 {    
  int fd;
  char * myfifo = "/tmp/myfifo";
  char buf[1024];

    while(1)
    {
        //READ actual depth fifo
        fd = open(myfifo, O_RDONLY | O_NONBLOCK);
        read(fd, buf, MAX_BUF);
        float depth = strtof(buf, NULL);
        printf("\ndepth actual: %4.2f", depth);              
    }    

     //Close read buffers
     close(fd);

     return 0;
  }

closed as off-topic by yaegashi, PersianGulf, jasonwryan, maxschlepzig, G-Man Aug 9 '15 at 8:23

  • This question does not appear to be about Unix or Linux within the scope defined in the help center.
If this question can be reworded to fit the rules in the help center, please edit the question.

  • It's totally wrong to send a string buffer representing a float by sizeof(float) bytes. And the listener immediately runs into a tight busy loop forever... What do you expect the program to achieve? – yaegashi Aug 9 '15 at 6:22
  • I’m sorry; what does this have to do with MarkWest Energy Partners?  Or are you talking about Modeling Workflow Engine or Multi-Word Expressions?   … … … … … … … … … … … … … … … … … … … …  Oh, wait; do you mean Minimum Working Example? – G-Man Aug 9 '15 at 8:13
  • We prefer Minimal, Complete, [and] Verifiable Examples (MCVEs) here (see also Short, Self-Contained, Correct (Compilable), Example (SSCCE).  Your example is neither complete nor compilable inasmuch it doesn’t show how talker() is invoked — specifically, how is it getting called more than once — so we have no way of understanding how “it works fine” for “a couple of data exchanges”, and, accordingly, no good way to understand how it “freezes”. – G-Man Aug 9 '15 at 8:15
  • Please don’t post code that fails to do the bare minimum, obvious error checking.  Your talker() routine creates and destroys the FIFO, so obviously it doesn’t always exist.  And yet your main() code says fd = open(myfifo, O_RDONLY | O_NONBLOCK) without checking for error (ENOENT), and then calls read(fd, buf, MAX_BUF) with a fd that might be -1.  And, even if you got the FIFO open, since it’s open in non-blocking mode, read can return 0 to indicate that no data are available (or it can return a partial message). – G-Man Aug 9 '15 at 8:16
  • 1
    @Calorified, you check the return value of each system call. Read the man page (man 2 read for the read function, for example. Syscalls are in section 2 of the manual, while library calls are in section 3) to see which return value means an error for each system or library call. Usually, 0 = success, -1 = error. If the return value indicates an error, you can check the variable errno (defined in <errno.h>) to see why there's an error. If a file failed to open because it didn't exist, errno will equal ENOENT. – Throw Away Account Aug 10 '15 at 4:20
0

You're only sending sizeof(float) bytes, which is only a substring of depthstring, whose actual size is strlen(depthstring)+1, not sizeof(float).

One thing you could do is eliminate the conversion to and from a string. Since both processes reading a named FIFO are on the same machine (no, FIFOs don't work over NFS), you can assume that a float is represented the same way in both processes. Therefore:

int talker(float depthright)
 {
   int fd;
   const char * myfifo = "/tmp/myfifo";

   mkfifo(myfifo, 0666);           /* create the FIFO (named pipe) */
   fd = open(myfifo, O_WRONLY/* | O_NONBLOCK*/);
   write(fd, &depthright, sizeof(depthright) );    

   /* close FIFO and delete fifo names from file system */
   close(fd);
   /* Don't delete the FIFO yet. The reader may not have opened
    * it yet.
    */

   return 0;
}

And then:

int main()
 {    
  int fd;
  const char * myfifo = "/tmp/myfifo";

    while(1)
    {
        //READ actual depth fifo
        fd = open(myfifo, O_RDONLY | O_NONBLOCK);
        float depth;
        read(fd, &depth, sizeof(depth));
        // Close read buffers now, since we open it with
        // each iteration. Waiting until after the loop
        // will result in only the last fd being closed.

        // Furthermore, there's a tight limit on how many
        // FDs you can have open at once.
        close(fd);    
        printf("\ndepth actual: %4.2f", depth);
        // Without this, libc may hold the output in a buffer
        // until the next float is read.
        fflush(stdout);
    }    
     /* NOT REACHED. The compiler may actually delete this code, since
      *  it can prove that this part will never be executed.
      */ 
     unlink(myfifo); 
     return 0;
  }
  • Actually, since fd is opened in O_NONBLOCK mode, read(fd, buf, MAX_BUF) will never block.  Even if it weren’t in O_NONBLOCK mode, it wouldn’t block until it receives MAX_BUF bytes; it would only block until it received one byte. – G-Man Aug 9 '15 at 8:18
  • Furthermore, there's a tight limit on how many. What is this limit, please? – Calorified Aug 9 '15 at 14:05
  • @G-Man, whoops, I didn't notice that he didn't have O_NONBLOCK commented out there. – Throw Away Account Aug 10 '15 at 3:59
  • @Calorified, the limit is defined somewhere in /proc/sys/, I can't remember where exactly. It can vary from system to system, and you can change it if you're root. There also seems to be a per-process setting you can modify with setrlimit (or ulimit -n from bash). – Throw Away Account Aug 10 '15 at 4:01
0

A small part of your problem may lie in the fact that you are doing an open inside your while (1) … read loop (without closing the resulting file descriptor in the loop).  Your code can be expected to accumulate hundreds of file descriptors for the FIFO.  Typically, after you hit a thousand, the open will start failing because of too many open files (EMFILE).

Not the answer you're looking for? Browse other questions tagged or ask your own question.