Need to explain behavior of read and named pipe












0















I've been working on project for college, in it I have some small scripts that perform operations on a simple database (such as select information), a server script that takes requests from various instances of a client script through a pipe named server.pipe and returns their result (usually a few lines of a text file) through the individual client's named pipe.



For multi line responses, I tried using a while loop in the client to keep reading from the pipe, I used something like this:



read response < $id.pipe
while [ $response != "end_result" ]; do
echo $response
read response < $id.pipe


This would sometimes return the full result, other times it would return part of it and other times none. When it didn't return the full result I think the running script was blocked by the pipe as debug statements showed me it didn't execute its final lines.



I fixed it with this instead



tail <$return_pipe &


I know that tail will read from a pipe even if its closed but I need help explaining the conditions causing the first one to fail as I'm writing a report on the assignment now. I've done a lot of reading and I sort of get it but I need help with the specifics.



If anyone's wondering, the server script is calling the script like this:



return_pipe=${ar[4]}.pipe
./select.sh ${ar[1]} ${ar[2]} ${ar[3]} >$return_pipe &


And the part of the select script returning the result is this



echo "start_result"
cut -d' ' -f$3 ./$1/$2
echo "end_result"


If anyone can help me understand this and explain it that'd be really appreciated. This is my first post so I hope I've formatted it appropriately too! Thanks










share|improve this question



























    0















    I've been working on project for college, in it I have some small scripts that perform operations on a simple database (such as select information), a server script that takes requests from various instances of a client script through a pipe named server.pipe and returns their result (usually a few lines of a text file) through the individual client's named pipe.



    For multi line responses, I tried using a while loop in the client to keep reading from the pipe, I used something like this:



    read response < $id.pipe
    while [ $response != "end_result" ]; do
    echo $response
    read response < $id.pipe


    This would sometimes return the full result, other times it would return part of it and other times none. When it didn't return the full result I think the running script was blocked by the pipe as debug statements showed me it didn't execute its final lines.



    I fixed it with this instead



    tail <$return_pipe &


    I know that tail will read from a pipe even if its closed but I need help explaining the conditions causing the first one to fail as I'm writing a report on the assignment now. I've done a lot of reading and I sort of get it but I need help with the specifics.



    If anyone's wondering, the server script is calling the script like this:



    return_pipe=${ar[4]}.pipe
    ./select.sh ${ar[1]} ${ar[2]} ${ar[3]} >$return_pipe &


    And the part of the select script returning the result is this



    echo "start_result"
    cut -d' ' -f$3 ./$1/$2
    echo "end_result"


    If anyone can help me understand this and explain it that'd be really appreciated. This is my first post so I hope I've formatted it appropriately too! Thanks










    share|improve this question

























      0












      0








      0








      I've been working on project for college, in it I have some small scripts that perform operations on a simple database (such as select information), a server script that takes requests from various instances of a client script through a pipe named server.pipe and returns their result (usually a few lines of a text file) through the individual client's named pipe.



      For multi line responses, I tried using a while loop in the client to keep reading from the pipe, I used something like this:



      read response < $id.pipe
      while [ $response != "end_result" ]; do
      echo $response
      read response < $id.pipe


      This would sometimes return the full result, other times it would return part of it and other times none. When it didn't return the full result I think the running script was blocked by the pipe as debug statements showed me it didn't execute its final lines.



      I fixed it with this instead



      tail <$return_pipe &


      I know that tail will read from a pipe even if its closed but I need help explaining the conditions causing the first one to fail as I'm writing a report on the assignment now. I've done a lot of reading and I sort of get it but I need help with the specifics.



      If anyone's wondering, the server script is calling the script like this:



      return_pipe=${ar[4]}.pipe
      ./select.sh ${ar[1]} ${ar[2]} ${ar[3]} >$return_pipe &


      And the part of the select script returning the result is this



      echo "start_result"
      cut -d' ' -f$3 ./$1/$2
      echo "end_result"


      If anyone can help me understand this and explain it that'd be really appreciated. This is my first post so I hope I've formatted it appropriately too! Thanks










      share|improve this question














      I've been working on project for college, in it I have some small scripts that perform operations on a simple database (such as select information), a server script that takes requests from various instances of a client script through a pipe named server.pipe and returns their result (usually a few lines of a text file) through the individual client's named pipe.



      For multi line responses, I tried using a while loop in the client to keep reading from the pipe, I used something like this:



      read response < $id.pipe
      while [ $response != "end_result" ]; do
      echo $response
      read response < $id.pipe


      This would sometimes return the full result, other times it would return part of it and other times none. When it didn't return the full result I think the running script was blocked by the pipe as debug statements showed me it didn't execute its final lines.



      I fixed it with this instead



      tail <$return_pipe &


      I know that tail will read from a pipe even if its closed but I need help explaining the conditions causing the first one to fail as I'm writing a report on the assignment now. I've done a lot of reading and I sort of get it but I need help with the specifics.



      If anyone's wondering, the server script is calling the script like this:



      return_pipe=${ar[4]}.pipe
      ./select.sh ${ar[1]} ${ar[2]} ${ar[3]} >$return_pipe &


      And the part of the select script returning the result is this



      echo "start_result"
      cut -d' ' -f$3 ./$1/$2
      echo "end_result"


      If anyone can help me understand this and explain it that'd be really appreciated. This is my first post so I hope I've formatted it appropriately too! Thanks







      bash concurrency pipe fifo






      share|improve this question













      share|improve this question











      share|improve this question




      share|improve this question










      asked Nov 24 '18 at 16:52









      Luke DeatonLuke Deaton

      31




      31
























          1 Answer
          1






          active

          oldest

          votes


















          0














          This happens because the fifo is not packet oriented. It's a stream.



          This means that multiple writes may concatenate in memory, and closing the pipe without reading all of the pipe buffer will discard the remainder.
          Whether this will happen is a race condition. Here's an order of events that works:




          • The server opens the fifo for msg1

          • The client opens the fifo for msg1

          • The server writes msg1

          • The server closes the fifo

          • The client reads msg1

          • The client closes the fifo

          • The above is repeated in the same order for msg2


          Here's a code example with sleeps to ensure a good order:



          rm fifo; mkfifo fifo
          {
          echo "hello" > fifo
          sleep 1
          echo "world" > fifo
          } &

          for i in 1 2
          do
          echo "Reading..."
          { read var; } < fifo
          sleep 1
          echo "Read: $var"
          done


          This will output what you'd expect:



          Reading...
          Read: hello
          Reading...
          Read: world


          Here's an order of events that fails:




          • The server opens the fifo for msg1

          • The client opens the fifo for msg1

          • The server writes msg1 and closes the fifo

          • The server opens the fifo for msg2

          • The server writes msg2 and closes the fifo

          • The client reads msg1

          • The client closes the fifo while msg2 is still unread. msg2 is now lost.


          Here are some sleeps to make that happen:



          rm fifo; mkfifo fifo
          {
          echo "hello" > fifo
          echo "world" > fifo
          } &

          for i in 1 2
          do
          echo "Reading..."
          { sleep 1; read var; } < fifo
          echo "Read: $var"
          done


          Now it will print:



          Reading...
          Read: hello
          Reading...


          and hang because world was lost.



          You should instead have opened the fifo once from both client the server, and kept writing to the same open FD. This would have ensured smooth and efficient communication without any loss of data.






          share|improve this answer
























          • Thank you so much, that really helps!

            – Luke Deaton
            Nov 24 '18 at 21:22











          Your Answer






          StackExchange.ifUsing("editor", function () {
          StackExchange.using("externalEditor", function () {
          StackExchange.using("snippets", function () {
          StackExchange.snippets.init();
          });
          });
          }, "code-snippets");

          StackExchange.ready(function() {
          var channelOptions = {
          tags: "".split(" "),
          id: "1"
          };
          initTagRenderer("".split(" "), "".split(" "), channelOptions);

          StackExchange.using("externalEditor", function() {
          // Have to fire editor after snippets, if snippets enabled
          if (StackExchange.settings.snippets.snippetsEnabled) {
          StackExchange.using("snippets", function() {
          createEditor();
          });
          }
          else {
          createEditor();
          }
          });

          function createEditor() {
          StackExchange.prepareEditor({
          heartbeatType: 'answer',
          autoActivateHeartbeat: false,
          convertImagesToLinks: true,
          noModals: true,
          showLowRepImageUploadWarning: true,
          reputationToPostImages: 10,
          bindNavPrevention: true,
          postfix: "",
          imageUploader: {
          brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
          contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
          allowUrls: true
          },
          onDemand: true,
          discardSelector: ".discard-answer"
          ,immediatelyShowMarkdownHelp:true
          });


          }
          });














          draft saved

          draft discarded


















          StackExchange.ready(
          function () {
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53460366%2fneed-to-explain-behavior-of-read-and-named-pipe%23new-answer', 'question_page');
          }
          );

          Post as a guest















          Required, but never shown

























          1 Answer
          1






          active

          oldest

          votes








          1 Answer
          1






          active

          oldest

          votes









          active

          oldest

          votes






          active

          oldest

          votes









          0














          This happens because the fifo is not packet oriented. It's a stream.



          This means that multiple writes may concatenate in memory, and closing the pipe without reading all of the pipe buffer will discard the remainder.
          Whether this will happen is a race condition. Here's an order of events that works:




          • The server opens the fifo for msg1

          • The client opens the fifo for msg1

          • The server writes msg1

          • The server closes the fifo

          • The client reads msg1

          • The client closes the fifo

          • The above is repeated in the same order for msg2


          Here's a code example with sleeps to ensure a good order:



          rm fifo; mkfifo fifo
          {
          echo "hello" > fifo
          sleep 1
          echo "world" > fifo
          } &

          for i in 1 2
          do
          echo "Reading..."
          { read var; } < fifo
          sleep 1
          echo "Read: $var"
          done


          This will output what you'd expect:



          Reading...
          Read: hello
          Reading...
          Read: world


          Here's an order of events that fails:




          • The server opens the fifo for msg1

          • The client opens the fifo for msg1

          • The server writes msg1 and closes the fifo

          • The server opens the fifo for msg2

          • The server writes msg2 and closes the fifo

          • The client reads msg1

          • The client closes the fifo while msg2 is still unread. msg2 is now lost.


          Here are some sleeps to make that happen:



          rm fifo; mkfifo fifo
          {
          echo "hello" > fifo
          echo "world" > fifo
          } &

          for i in 1 2
          do
          echo "Reading..."
          { sleep 1; read var; } < fifo
          echo "Read: $var"
          done


          Now it will print:



          Reading...
          Read: hello
          Reading...


          and hang because world was lost.



          You should instead have opened the fifo once from both client the server, and kept writing to the same open FD. This would have ensured smooth and efficient communication without any loss of data.






          share|improve this answer
























          • Thank you so much, that really helps!

            – Luke Deaton
            Nov 24 '18 at 21:22
















          0














          This happens because the fifo is not packet oriented. It's a stream.



          This means that multiple writes may concatenate in memory, and closing the pipe without reading all of the pipe buffer will discard the remainder.
          Whether this will happen is a race condition. Here's an order of events that works:




          • The server opens the fifo for msg1

          • The client opens the fifo for msg1

          • The server writes msg1

          • The server closes the fifo

          • The client reads msg1

          • The client closes the fifo

          • The above is repeated in the same order for msg2


          Here's a code example with sleeps to ensure a good order:



          rm fifo; mkfifo fifo
          {
          echo "hello" > fifo
          sleep 1
          echo "world" > fifo
          } &

          for i in 1 2
          do
          echo "Reading..."
          { read var; } < fifo
          sleep 1
          echo "Read: $var"
          done


          This will output what you'd expect:



          Reading...
          Read: hello
          Reading...
          Read: world


          Here's an order of events that fails:




          • The server opens the fifo for msg1

          • The client opens the fifo for msg1

          • The server writes msg1 and closes the fifo

          • The server opens the fifo for msg2

          • The server writes msg2 and closes the fifo

          • The client reads msg1

          • The client closes the fifo while msg2 is still unread. msg2 is now lost.


          Here are some sleeps to make that happen:



          rm fifo; mkfifo fifo
          {
          echo "hello" > fifo
          echo "world" > fifo
          } &

          for i in 1 2
          do
          echo "Reading..."
          { sleep 1; read var; } < fifo
          echo "Read: $var"
          done


          Now it will print:



          Reading...
          Read: hello
          Reading...


          and hang because world was lost.



          You should instead have opened the fifo once from both client the server, and kept writing to the same open FD. This would have ensured smooth and efficient communication without any loss of data.






          share|improve this answer
























          • Thank you so much, that really helps!

            – Luke Deaton
            Nov 24 '18 at 21:22














          0












          0








          0







          This happens because the fifo is not packet oriented. It's a stream.



          This means that multiple writes may concatenate in memory, and closing the pipe without reading all of the pipe buffer will discard the remainder.
          Whether this will happen is a race condition. Here's an order of events that works:




          • The server opens the fifo for msg1

          • The client opens the fifo for msg1

          • The server writes msg1

          • The server closes the fifo

          • The client reads msg1

          • The client closes the fifo

          • The above is repeated in the same order for msg2


          Here's a code example with sleeps to ensure a good order:



          rm fifo; mkfifo fifo
          {
          echo "hello" > fifo
          sleep 1
          echo "world" > fifo
          } &

          for i in 1 2
          do
          echo "Reading..."
          { read var; } < fifo
          sleep 1
          echo "Read: $var"
          done


          This will output what you'd expect:



          Reading...
          Read: hello
          Reading...
          Read: world


          Here's an order of events that fails:




          • The server opens the fifo for msg1

          • The client opens the fifo for msg1

          • The server writes msg1 and closes the fifo

          • The server opens the fifo for msg2

          • The server writes msg2 and closes the fifo

          • The client reads msg1

          • The client closes the fifo while msg2 is still unread. msg2 is now lost.


          Here are some sleeps to make that happen:



          rm fifo; mkfifo fifo
          {
          echo "hello" > fifo
          echo "world" > fifo
          } &

          for i in 1 2
          do
          echo "Reading..."
          { sleep 1; read var; } < fifo
          echo "Read: $var"
          done


          Now it will print:



          Reading...
          Read: hello
          Reading...


          and hang because world was lost.



          You should instead have opened the fifo once from both client the server, and kept writing to the same open FD. This would have ensured smooth and efficient communication without any loss of data.






          share|improve this answer













          This happens because the fifo is not packet oriented. It's a stream.



          This means that multiple writes may concatenate in memory, and closing the pipe without reading all of the pipe buffer will discard the remainder.
          Whether this will happen is a race condition. Here's an order of events that works:




          • The server opens the fifo for msg1

          • The client opens the fifo for msg1

          • The server writes msg1

          • The server closes the fifo

          • The client reads msg1

          • The client closes the fifo

          • The above is repeated in the same order for msg2


          Here's a code example with sleeps to ensure a good order:



          rm fifo; mkfifo fifo
          {
          echo "hello" > fifo
          sleep 1
          echo "world" > fifo
          } &

          for i in 1 2
          do
          echo "Reading..."
          { read var; } < fifo
          sleep 1
          echo "Read: $var"
          done


          This will output what you'd expect:



          Reading...
          Read: hello
          Reading...
          Read: world


          Here's an order of events that fails:




          • The server opens the fifo for msg1

          • The client opens the fifo for msg1

          • The server writes msg1 and closes the fifo

          • The server opens the fifo for msg2

          • The server writes msg2 and closes the fifo

          • The client reads msg1

          • The client closes the fifo while msg2 is still unread. msg2 is now lost.


          Here are some sleeps to make that happen:



          rm fifo; mkfifo fifo
          {
          echo "hello" > fifo
          echo "world" > fifo
          } &

          for i in 1 2
          do
          echo "Reading..."
          { sleep 1; read var; } < fifo
          echo "Read: $var"
          done


          Now it will print:



          Reading...
          Read: hello
          Reading...


          and hang because world was lost.



          You should instead have opened the fifo once from both client the server, and kept writing to the same open FD. This would have ensured smooth and efficient communication without any loss of data.







          share|improve this answer












          share|improve this answer



          share|improve this answer










          answered Nov 24 '18 at 20:59









          that other guythat other guy

          73.2k885123




          73.2k885123













          • Thank you so much, that really helps!

            – Luke Deaton
            Nov 24 '18 at 21:22



















          • Thank you so much, that really helps!

            – Luke Deaton
            Nov 24 '18 at 21:22

















          Thank you so much, that really helps!

          – Luke Deaton
          Nov 24 '18 at 21:22





          Thank you so much, that really helps!

          – Luke Deaton
          Nov 24 '18 at 21:22




















          draft saved

          draft discarded




















































          Thanks for contributing an answer to Stack Overflow!


          • Please be sure to answer the question. Provide details and share your research!

          But avoid



          • Asking for help, clarification, or responding to other answers.

          • Making statements based on opinion; back them up with references or personal experience.


          To learn more, see our tips on writing great answers.




          draft saved


          draft discarded














          StackExchange.ready(
          function () {
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53460366%2fneed-to-explain-behavior-of-read-and-named-pipe%23new-answer', 'question_page');
          }
          );

          Post as a guest















          Required, but never shown





















































          Required, but never shown














          Required, but never shown












          Required, but never shown







          Required, but never shown

































          Required, but never shown














          Required, but never shown












          Required, but never shown







          Required, but never shown







          Popular posts from this blog

          404 Error Contact Form 7 ajax form submitting

          How to know if a Active Directory user can login interactively

          Refactoring coordinates for Minecraft Pi buildings written in Python