Unix Programming - fd redirection and gdb

This is Interesting: Free IT Magazines  
Home > Archive > Unix Programming > January 2007 > fd redirection and gdb





You are viewing an archived Text-only version of the thread. To view this thread in it's original format and/or if you want to reply to this thread please [click here]

Author fd redirection and gdb
Daniel C. Bastos

2007-01-28, 7:20 pm

I'm going to describe the context to ask my question, but I don't know
what the problem is, so it's possible that I will not describe the
context very well.

I wrote a program A that talks to another program B in order to get some
tasks done; B receives one command per line, and may return many
lines. Everything that B answers, A prints it verbatim to another
program --- and this scenario repeats many times.

When A starts, A runs pipe(), then fork(), redirects file descriptors,
and execl(); so A connects the stdin of B on some file descriptor that
it will monitor. Here is the code that does this job.

r = pipe(fd); if (r < 0) { strerr_sys(1); }
r = fork(); if (r < 0) { strerr_sys(1); }

if (r > 0) {
peer_attach(fd[0]); pg = &user[2];
pg->ou.f = fd[1]; /* doc this */
}

else { /* redirect 0 && 1, then execl */
if (fd[0] != 0) { if (dup2(fd[0], 0) != 0) { _exit(1); } close(fd[0]); }
if (fd[1] != 1) { if (dup2(fd[1], 1) != 1) { _exit(1); } close(fd[1]); }
execl(plug, "plugger", (void*) 0); _exit(4);
}

With peer_attach(), I add fd[0] to a set of listening sockets, so that
anything that B speaks, I can grab through a loop somewhere
else. Whenever I need to say something to B, I speak through pg->ou.f
which is fd[1].

Before ``plugger'' runs, I redirect its stdin and stdout; the file
descriptors returned from pipe() are already connected on one another,
so whatever I write on fd[1] is read on fd[0], so I dup2() fd[0] to 0
and dup2() fd[1] to 1 in the child process --- which is B.

If I run the program on the shell, and I monitor it with a log file, I
see everything as I expected. But if I run it through GDB, then I notice
a behavior which I did not expect and don't know how to explain.

Here is a verbal simulation: I set a breakpoint in a function that runs
when A wants to say something to B. If I say ``continue'' right after
stopping there, it works; A speaks, B answers; all normal. If I say
``next'' a few times, and then ``continue'' it also works.

But if I say ``next'' on the line that calls write() so that A can say
something to B, then A says what it wanted to say, and B answers and
then A is supposed to forward this captured output to some other place,
but it seems to echo the output back to B, and B complains it doesn't
understand, as it should.

The problem seems to happen when I say ``next'' on the write() line; if
I say ``continue'' at the line, it works as I expected. The problem is
as if I were writing on the wrong file descriptor after I grabbed the
answer from B.

In the GDB book at

http://www.hlrs.de/organization/amt...b/doc/gdb-6.3df

I read a warning on section 4.2 ``starting your program'' that says
``Warning: While input and output redirection work, you cannot use pipes
to pass the output of the program you are debugging to another program;
if you attempt this, GDB is likely to wind up debugging the wrong
program.''

I don't understand what ``is likely wind up debugging the wrong
program'' means. I don't think GDB ends up debugging the wrong program
here; I do not follow the fork and I keep debugging the same program;
the right program: program A.

However, I do use a pipe to pass the output of the program I am
debugging --- which is A --- to another program --- which is B --- and I
use a socket to pass what I capture from B to another (remote) program.

Can someone explain the behavior or give me some instruction to
investigate the problem more accurately? Thank you.
Barry Margolin

2007-01-28, 7:20 pm

In article <20070128172753.6d9ff54c.dbast0s@yahoo.com.br>,
"Daniel C. Bastos" <dbast0s@yahoo.com.br> wrote:

> I'm going to describe the context to ask my question, but I don't know
> what the problem is, so it's possible that I will not describe the
> context very well.
>
> I wrote a program A that talks to another program B in order to get some
> tasks done; B receives one command per line, and may return many
> lines. Everything that B answers, A prints it verbatim to another
> program --- and this scenario repeats many times.
>
> When A starts, A runs pipe(), then fork(), redirects file descriptors,
> and execl(); so A connects the stdin of B on some file descriptor that
> it will monitor. Here is the code that does this job.
>
> r = pipe(fd); if (r < 0) { strerr_sys(1); }
> r = fork(); if (r < 0) { strerr_sys(1); }
>
> if (r > 0) {
> peer_attach(fd[0]); pg = &user[2];
> pg->ou.f = fd[1]; /* doc this */
> }
>
> else { /* redirect 0 && 1, then execl */
> if (fd[0] != 0) { if (dup2(fd[0], 0) != 0) { _exit(1); } close(fd[0]); }
> if (fd[1] != 1) { if (dup2(fd[1], 1) != 1) { _exit(1); } close(fd[1]); }
> execl(plug, "plugger", (void*) 0); _exit(4);
> }
>
> With peer_attach(), I add fd[0] to a set of listening sockets, so that
> anything that B speaks, I can grab through a loop somewhere
> else. Whenever I need to say something to B, I speak through pg->ou.f
> which is fd[1].


If you want bidirectional communication with the program, you need TWO
pipes. Although some implementations allow full-duplex use of a single
pipe, it's not portable.

>
> Before ``plugger'' runs, I redirect its stdin and stdout; the file
> descriptors returned from pipe() are already connected on one another,
> so whatever I write on fd[1] is read on fd[0], so I dup2() fd[0] to 0
> and dup2() fd[1] to 1 in the child process --- which is B.
>
> If I run the program on the shell, and I monitor it with a log file, I
> see everything as I expected. But if I run it through GDB, then I notice
> a behavior which I did not expect and don't know how to explain.
>
> Here is a verbal simulation: I set a breakpoint in a function that runs
> when A wants to say something to B. If I say ``continue'' right after
> stopping there, it works; A speaks, B answers; all normal. If I say
> ``next'' a few times, and then ``continue'' it also works.
>
> But if I say ``next'' on the line that calls write() so that A can say
> something to B, then A says what it wanted to say, and B answers and
> then A is supposed to forward this captured output to some other place,
> but it seems to echo the output back to B, and B complains it doesn't
> understand, as it should.


I can't explain this, except maybe as a gdb bug.

>
> The problem seems to happen when I say ``next'' on the write() line; if
> I say ``continue'' at the line, it works as I expected. The problem is
> as if I were writing on the wrong file descriptor after I grabbed the
> answer from B.
>
> In the GDB book at
>
> http://www.hlrs.de/organization/amt...b/doc/gdb-6.3df
>
> I read a warning on section 4.2 ``starting your program'' that says
> ``Warning: While input and output redirection work, you cannot use pipes
> to pass the output of the program you are debugging to another program;
> if you attempt this, GDB is likely to wind up debugging the wrong
> program.''


I think it's talking about shell pipelines, e.g.

gdb program | someother program

not internal use of pipes within the program.

--
Barry Margolin, barmar@alum.mit.edu
Arlington, MA
*** PLEASE post questions in newsgroups, not directly to me ***
*** PLEASE don't copy me on replies, I'll read them in the group ***
Alan Curry

2007-01-29, 7:20 am

In article <barmar-D7D638.17431028012007@comcast.dca.giganews.com>,
Barry Margolin <barmar@alum.mit.edu> wrote:
>In article <20070128172753.6d9ff54c.dbast0s@yahoo.com.br>,
> "Daniel C. Bastos" <dbast0s@yahoo.com.br> wrote:
>
>I think it's talking about shell pipelines, e.g.
>
>gdb program | someother program


I think it means
(gdb) run | someother
as opposed to
(gdb) run < inputfile
which actually does work.

--
Alan Curry
pacman@world.std.com
Sponsored Links






Free braindumps | Software forum | Database administration forum

Copyright 2003 - 2008 webservertalk.com