Welcome to the { mindfrost82.com } forums.

You are currently viewing our boards as a guest which gives you limited access to view most discussions and access our other features. By joining our free community you will have access to post topics, communicate privately with other members (PM), respond to polls, upload content and access many other special features. Registration is fast, simple and absolutely free so please, join our community today!

If you have any problems with the registration process or your account login, please contact contact us.

Go Back   { mindfrost82.com } > Gadget Corner > Tech Newsgroups > Linux > Linux Networking

Reply
 
LinkBack Thread Tools Search this Thread Display Modes
  #1 (permalink)  
Old 03-21-2008, 12:43 AM
Knight
 
Posts: n/a
Help: redirecting process input/output

Hi,
below is a simplified version of my program. I am trying to
implement a version of popen() where my keyboard input goes to a
process's standard input; and its standard output goes to my screen
(well - without just running the program directly :-)) However, it's
not working, the child-to-parent pipe c2p never gets written to (at
least with /bin/ls and /bin/date). Is it wrong to close c2p[0] and
p2c[1] in child?

Invoke as: <progname> /bin/someprog arg1 arg2 arg3 (args for someprog)
e.g.
<progname> /bin/ls .

#include <sys/select.h>
#include <stdio.h>
#include <unistd.h>

int main (int argc, char *argv[])
{
int p2c[2], c2p[2], count;
char buf[1024];

pipe(p2c); pipe(c2p);
if (fork()) {
fd_set r;
close(p2c[0]); close(c2p[1]);
while (1) {
FD_ZERO(&r);
FD_SET(0, &r);
FD_SET(c2p[0], &r);
select(c2p[0], &r, NULL, NULL, NULL);
if (FD_ISSET(c2p[0], &r)) {
if ((count = read(c2p[0], buf, 1024))
> 0) {

write(1, buf, count);
}
}
if (FD_ISSET(0, &r)) {
if ((count = read(0, buf, 1024)) > 0)
{
write(p2c[1], buf, count);
}
}
}
} else {
close(0);
dup(p2c[0]);
close(p2c[0]);
close(1);
dup(c2p[1]);
close(c2p[1]);
execvp(argv[1], &argv[1]);
}
return 0;
}
Reply With Quote
  #2 (permalink)  
Old 03-21-2008, 09:51 AM
Robert Harris
 
Posts: n/a
Re: Help: redirecting process input/output

Knight wrote:
> Hi,
> below is a simplified version of my program. I am trying to
> implement a version of popen() where my keyboard input goes to a
> process's standard input; and its standard output goes to my screen
> (well - without just running the program directly :-)) However, it's
> not working, the child-to-parent pipe c2p never gets written to (at
> least with /bin/ls and /bin/date). Is it wrong to close c2p[0] and
> p2c[1] in child?


No

>
> Invoke as: <progname> /bin/someprog arg1 arg2 arg3 (args for someprog)
> e.g.
> <progname> /bin/ls .
>
> #include <sys/select.h>
> #include <stdio.h>
> #include <unistd.h>
>
> int main (int argc, char *argv[])
> {
> int p2c[2], c2p[2], count;
> char buf[1024];
>
> pipe(p2c); pipe(c2p);
> if (fork()) {
> fd_set r;
> close(p2c[0]); close(c2p[1]);
> while (1) {
> FD_ZERO(&r);
> FD_SET(0, &r);
> FD_SET(c2p[0], &r);
> select(c2p[0], &r, NULL, NULL, NULL);


First parameter should have 1 added
Robert

> if (FD_ISSET(c2p[0], &r)) {
> if ((count = read(c2p[0], buf, 1024))
>> 0) {

> write(1, buf, count);
> }
> }
> if (FD_ISSET(0, &r)) {
> if ((count = read(0, buf, 1024)) > 0)
> {
> write(p2c[1], buf, count);
> }
> }
> }
> } else {
> close(0);
> dup(p2c[0]);
> close(p2c[0]);
> close(1);
> dup(c2p[1]);
> close(c2p[1]);
> execvp(argv[1], &argv[1]);
> }
> return 0;
> }

Reply With Quote
  #3 (permalink)  
Old 03-21-2008, 09:06 PM
Knight
 
Posts: n/a
Re: Help: redirecting process input/output

On Mar 21, 1:51*am, Robert Harris <robert.f.har...@blueyonder.co.uk>
wrote:
> > * * * * * * * * * * * * select(c2p[0], &r, NULL,NULL, NULL);

>
> First parameter should have 1 added
> Robert


Thank you! Last place I suspected!
Sorry, a simple "Thank You" does not adequately express the depth of
my gratitude for catching this bug.

THANK YOU!!!! THANK YOU!!!! THANK YOU!!!! THANK YOU!!!! THANK YOU!!!!
Vote Harris for World President!

A little better.
Reply With Quote
  #4 (permalink)  
Old 03-22-2008, 03:35 PM
David Schwartz
 
Posts: n/a
Re: Help: redirecting process input/output

On Mar 21, 1:06 pm, Knight <knightt...@yahoo.com> wrote:

> Thank you! Last place I suspected!
> Sorry, a simple "Thank You" does not adequately express the depth of
> my gratitude for catching this bug.
>
> THANK YOU!!!! THANK YOU!!!! THANK YOU!!!! THANK YOU!!!! THANK YOU!!!!
> Vote Harris for World President!
>
> A little better.


By the way, your code is largely operating by luck. It has a very
serious, and very subtle, bug that can lead to deadlock.

You cannot assume that it is safe to refuse to read from one
connection until you finish writing to another. If two processes do
that, they can wind up each refusing to read until the other reads,
which is fatal.

You also didn't set the sockets non-blocking, which can also lead to
deadlock for much the same reason.

> if (FD_ISSET(c2p[0], &r)) {
> if ((count = read(c2p[0], buf, 1024))
>> 0) {

> write(1, buf, count);
> }
> }
> if (FD_ISSET(0, &r)) {
> if ((count = read(0, buf, 1024)) > 0)
> {
> write(p2c[1], buf, count);
> }
> }


Notice that you do not perform the second 'read' until the first
'write' completes? But your 'write' can only complete if there is
sufficient space in the pipe, which may require the consuming process
to 'read' from the pipe. But the consuming process might be blocked in
'write' waiting for space in the pipe which will only be made
available by your second 'read'. So you are each waiting for the
other.

You must not wait to call the second 'read' until the first 'write'
completes.

You can get the same deadlock the other way around as well. You could
be blocked in the first 'write', unable to find buffer space because
the program you are trying to 'write' to cannot call 'read' until you
perform the first 'read' on the next pass of your 'select' loop.

Sorry for the bad news.

The simplest fix is just to 'fork' and use one process for each
direction. Each process blocks in 'read' and then blocks in 'write'.
The way, one process blocking in 'write' won't keep the other one from
'read'ing.

Otherwise, you have to use 'select' for your writes as well, and you
must set the sockets non-blocking.

DS
Reply With Quote
  #5 (permalink)  
Old 03-24-2008, 07:12 AM
Knight
 
Posts: n/a
Re: Help: redirecting process input/output

On Mar 22, 6:35*am, David Schwartz <dav...@webmaster.com> wrote:
>
> By the way, your code is largely operating by luck. It has a very
> serious, and very subtle, bug that can lead to deadlock.
>
> You cannot assume that it is safe to refuse to read from one
> connection until you finish writing to another. If two processes do
> that, they can wind up each refusing to read until the other reads,
> which is fatal.
>
> You also didn't set the sockets non-blocking, which can also lead to
> deadlock for much the same reason.
>
> > * * * * * * * * * * * * if (FD_ISSET(c2p[0], &r)) {
> > * * * * * * * * * * * * * * * * if ((count = read(c2p[0], buf, 1024))
> >> 0) {

> > * * * * * * * * * * * * * * * * * * * * write(1, buf, count);
> > * * * * * * * * * * * * * * * * }
> > * * * * * * * * * * * * }
> > * * * * * * * * * * * * if (FD_ISSET(0, &r)) {
> > * * * * * * * * * * * * * * * * if ((count = read(0, buf, 1024)) > 0)
> > {
> > * * * * * * * * * * * * * * * * * * * * write(p2c[1], buf, count);
> > * * * * * * * * * * * * * * * * }
> > * * * * * * * * * * * * }

>
> Notice that you do not perform the second 'read' until the first
> 'write' completes? But your 'write' can only complete if there is
> sufficient space in the pipe, which may require the consuming process
> to 'read' from the pipe. But the consuming process might be blocked in
> 'write' waiting for space in the pipe which will only be made
> available by your second 'read'. So you are each waiting for the
> other.
>
> You must not wait to call the second 'read' until the first 'write'
> completes.
>
> You can get the same deadlock the other way around as well. You could
> be blocked in the first 'write', unable to find buffer space because
> the program you are trying to 'write' to cannot call 'read' until you
> perform the first 'read' on the next pass of your 'select' loop.
>
> Sorry for the bad news.
>
> The simplest fix is just to 'fork' and use one process for each
> direction. Each process blocks in 'read' and then blocks in 'write'.
> The way, one process blocking in 'write' won't keep the other one from
> 'read'ing.
>
> Otherwise, you have to use 'select' for your writes as well, and you
> must set the sockets non-blocking.
>
> DS


Sorry, I didn't understand this bit. The first write (in the parent)
is to file descriptor 1 (tty output) and not to the pipe. Similarly
the second read is from fd 0 (tty input).
I don't think you're saying they will block because of insufficient
space in the pipe, right?

Or is this the scenario you're visualizing: Parent writes to p2c[1]
but blocks due to insufficient space. Child was already blocked on a
write to its 1 (which used to be c2p[1] before all the close()/dup()
stuff). Now neither will advance because neither is reading?

BTW in my situation (embedded system, limited RAM) I think it will be
better to set sockets nonblocking, do select() for writes and reads
both, and retry them; rather than 2 forks.
Reply With Quote
  #6 (permalink)  
Old 03-24-2008, 12:26 PM
David Schwartz
 
Posts: n/a
Re: Help: redirecting process input/output

On Mar 23, 11:12 pm, Knight <knightt...@yahoo.com> wrote:

> Or is this the scenario you're visualizing: Parent writes
>to p2c[1] but blocks due to insufficient space. Child was
> already blocked on a write to its 1 (which used to be
> c2p[1] before all the close()/dup() stuff). Now neither
> will advance because neither is reading?


That is definitely one of the two ways it can deadlock.

> BTW in my situation (embedded system, limited RAM) I think
> it will be better to set sockets nonblocking, do select()
> for writes and reads both, and retry them; rather than 2
> forks.


That's a good solution, but it's a bit tricky to implement correctly.

DS
Reply With Quote
Reply

  { mindfrost82.com } > Gadget Corner > Tech Newsgroups > Linux > Linux Networking


Thread Tools Search this Thread
Search this Thread:

Advanced Search
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are Off
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are On



All times are GMT. The time now is 11:17 AM.


Powered by vBulletin, Copyright ©2000 - 2008, Jelsoft Enterprises Ltd.
Search Engine Friendly URLs by vBSEO 3.1.0 ©2007, Crawlability, Inc.
© 1999-2008 mindfrost82.com v11.0


Sponsors:
Montana Music | Payday Loan | Mortgage calculator | Debt Consolidation | Per Insurance



1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114