Need to explain behavior of read and named pipe
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
add a comment |
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
add a comment |
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
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
bash concurrency pipe fifo
asked Nov 24 '18 at 16:52
Luke DeatonLuke Deaton
31
31
add a comment |
add a comment |
1 Answer
1
active
oldest
votes
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.
Thank you so much, that really helps!
– Luke Deaton
Nov 24 '18 at 21:22
add a comment |
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
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
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.
Thank you so much, that really helps!
– Luke Deaton
Nov 24 '18 at 21:22
add a comment |
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.
Thank you so much, that really helps!
– Luke Deaton
Nov 24 '18 at 21:22
add a comment |
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.
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.
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
add a comment |
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
add a comment |
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.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
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