{"id":148,"date":"2008-03-09T17:00:20","date_gmt":"2008-03-10T01:00:20","guid":{"rendered":"http:\/\/www.outflux.net\/blog\/archives\/2008\/03\/09\/using-select-on-a-fifo\/"},"modified":"2008-03-09T22:59:53","modified_gmt":"2008-03-10T06:59:53","slug":"using-select-on-a-fifo","status":"publish","type":"post","link":"https:\/\/outflux.net\/blog\/archives\/2008\/03\/09\/using-select-on-a-fifo\/","title":{"rendered":"using select on a fifo"},"content":{"rendered":"<p>The right way to handle on-going input from file descriptors is to use <code>select()<\/code>.  All readable events are flagged (one such event is &#8220;end of file&#8221;, which is indicated by a 0-sized <code>read()<\/code>).  For example, if we&#8217;re reading from file descriptor <code>fd<\/code>:<\/p>\n<pre>\r\n  fd_set rfds;\r\n  int rc;\r\n\r\n  FD_ZERO(&amp;rfds);\r\n  FD_SET(fd, &amp;rfds);\r\n\r\n  tv.tv_sec = 1;\r\n  tv.tv_usec = 0;\r\n\r\n  rc = select(fd + 1, &amp;rfds, NULL, NULL, &amp;tv);\r\n  if (rc &gt; 0) {\r\n    char buf[80];\r\n    ssize_t got = read(fd, buf, sizeof(buf));\r\n    if (got &lt; 0) {\r\n      perror(\"read\");\r\n      return 1;\r\n    }\r\n    else if (got == 0) {\r\n      printf(\"EOF\\\\n\");\r\n      return 1;\r\n    }\r\n    else {\r\n      printf(\"read bytes: %d\\\\n\", got);\r\n    }\r\n  }\r\n<\/pre>\n<p>When dealing with sockets, the above loop is sane &#8212; EOF means the other end hung up and you&#8217;ll never get more data from the file descriptor.  In the case of a FIFO, however, &#8220;0 length read&#8221; means there are no more FIFO writers &#8212; but more could attach later and continue feeding in data!  The problem with this is that select misbehaves and marks the file descriptor as &#8220;EOF&#8221; forever.  Only the initial <code>select()<\/code> call blocks until there is something to read &#8212; once it hits EOF, select will always immediately return, defeating the purpose of <code>select()<\/code>.<\/p>\n<p>One solution is to re-open the FIFO, but you might <a href=\"https:\/\/launchpad.net\/bugs\/200299\">miss writers<\/a> between your 0-length <code>read()<\/code> and the next <code>open()<\/code>.<\/p>\n<p>The seemingly correct <a href=\"http:\/\/fixunix.com\/unix\/350803-use-select-fifo-after-has-closed.html\">solution<\/a> is rather simple: the FIFO reader should open the FIFO as a writer also.  In this case, <code>select()<\/code> never thinks all the writers have vanished, so there is never an EOF condition, and the reader never misses any writers.  So, instead of <code>O_RDONLY<\/code>, use:<\/p>\n<pre>\r\nfd = open(FIFO_PATHNAME, <b>O_RDWR<\/b> | O_NONBLOCK);\r\n<\/pre>\n<p style='text-align:left'>&copy; 2008, <a href=\"https:\/\/outflux.net\/blog\/\">Kees Cook<\/a>. This work is licensed under a <a rel=\"license\" href=\"http:\/\/creativecommons.org\/licenses\/by-sa\/4.0\/\">Creative Commons Attribution-ShareAlike 4.0 License<\/a>.<br \/><a rel=\"license\" href=\"http:\/\/creativecommons.org\/licenses\/by-sa\/4.0\/\"><img decoding=\"async\" alt=\"CC BY-SA 4.0\" style=\"border-width:0\" src=\"https:\/\/i.creativecommons.org\/l\/by-sa\/4.0\/88x31.png\" \/><\/a> <\/p>\n","protected":false},"excerpt":{"rendered":"<p>The right way to handle on-going input from file descriptors is to use select(). All readable events are flagged (one such event is &#8220;end of file&#8221;, which is indicated by a 0-sized read()). For example, if we&#8217;re reading from file descriptor fd: fd_set rfds; int rc; FD_ZERO(&amp;rfds); FD_SET(fd, &amp;rfds); tv.tv_sec = 1; tv.tv_usec = 0; [&hellip;]<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[14],"tags":[],"_links":{"self":[{"href":"https:\/\/outflux.net\/blog\/wp-json\/wp\/v2\/posts\/148"}],"collection":[{"href":"https:\/\/outflux.net\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/outflux.net\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/outflux.net\/blog\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/outflux.net\/blog\/wp-json\/wp\/v2\/comments?post=148"}],"version-history":[{"count":0,"href":"https:\/\/outflux.net\/blog\/wp-json\/wp\/v2\/posts\/148\/revisions"}],"wp:attachment":[{"href":"https:\/\/outflux.net\/blog\/wp-json\/wp\/v2\/media?parent=148"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/outflux.net\/blog\/wp-json\/wp\/v2\/categories?post=148"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/outflux.net\/blog\/wp-json\/wp\/v2\/tags?post=148"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}