Unix Programming - stdout redirection problem

This is Interesting: Free IT Magazines  
Home > Archive > Unix Programming > June 2004 > stdout redirection problem





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 stdout redirection problem
Rickard

2004-06-15, 5:56 pm

Hi,

I have some problems getting this simple C program to work on Linux:

#include <stdio.h> /* fprintf, stderr */
#include <unistd.h> /* fork, pipe, read, write */
#include <sys/poll.h> /* poll */

static void WriteAByte(int fd);
static void ReadAByte(int fd);

int main(void)
{
int pipes[2];
int pipes2[2];

pipe(pipes);
pipe(pipes2);

if (0 == fork())
{
dup2(pipes[0], 0);
dup2(pipes2[0], 1);

ReadAByte(0);
WriteAByte(1);
}
else
{
WriteAByte(pipes[1]);
ReadAByte(pipes2[1]);
}

return (0);
}

void ReadAByte(int fd)
{
struct pollfd fds;
int res;
char byte;

fds.fd = fd;
fds.events = POLLIN;

res = poll(&fds, 1, 100);
if (res != 0)
{
(void)fprintf(stderr,
">>%d Got something (%d)<<\n",
getpid(),
read(fd, &byte, 1));
}
}

void WriteAByte(int fd)
{
char byte = 'x';
(void)fprintf(stderr,
">>%d Wrote something (%d)<<\n",
getpid(),
write(fd, &byte, 1));
}

On solaris (5.6 Generic_105181-31 sun4u sparc SUNW,Ultra-2) the
program works fine:
[vbcol=seagreen]
> ./pipes
)<<

On Linux however (2.4.21-15.ELsmp i686 GNU/Linux) write to stdout
fails with errno 9, Bad file number.
[vbcol=seagreen]
> ./pipes

Any help/input is appreciated.

Regards,
Rickard
sean larsson

2004-06-15, 5:56 pm

On 15 Jun 2004 09:30:26 -0700
r_holgersson@hotmail.com (Rickard) wrote:

> Hi,
>
> I have some problems getting this simple C program to work on Linux:
>
> #include <stdio.h> /* fprintf, stderr */
> #include <unistd.h> /* fork, pipe, read, write */
> #include <sys/poll.h> /* poll */
>
> static void WriteAByte(int fd);
> static void ReadAByte(int fd);
>
> int main(void)
> {
> int pipes[2];
> int pipes2[2];
>
> pipe(pipes);
> pipe(pipes2);
>
> if (0 == fork())
> {
> dup2(pipes[0], 0);
> dup2(pipes2[0], 1);
>
> ReadAByte(0);
> WriteAByte(1);
> }

you are dup'ing the read end of a pipe to STDOUT. stdout is a writing stream, not a reading one. when u call WriteAByte(1) you are now trying to write to the read end of a pipe, on linux this returns EBADF. and you haven't checked the error returns of
functions either.

> else
> {
> WriteAByte(pipes[1]);
> ReadAByte(pipes2[1]);
> }
>
> return (0);
> }
>
> void ReadAByte(int fd)
> {
> struct pollfd fds;
> int res;
> char byte;
>
> fds.fd = fd;
> fds.events = POLLIN;
>
> res = poll(&fds, 1, 100);
> if (res != 0)
> {
> (void)fprintf(stderr,
> ">>%d Got something (%d)<<\n",
> getpid(),
> read(fd, &byte, 1));
> }
> }
>
> void WriteAByte(int fd)
> {
> char byte = 'x';
> (void)fprintf(stderr,
> ">>%d Wrote something (%d)<<\n",
> getpid(),
> write(fd, &byte, 1));
> }
>
> On solaris (5.6 Generic_105181-31 sun4u sparc SUNW,Ultra-2) the
> program works fine:
>
> )<<
>
> On Linux however (2.4.21-15.ELsmp i686 GNU/Linux) write to stdout
> fails with errno 9, Bad file number.
>
>
> Any help/input is appreciated.
>
> Regards,
> Rickard




--
-sean
Barry Margolin

2004-06-15, 5:56 pm

In article <6fd342f2.0406150830.31c5413d@posting.google.com>,
r_holgersson@hotmail.com (Rickard) wrote:

> Hi,
>
> I have some problems getting this simple C program to work on Linux:
>
> #include <stdio.h> /* fprintf, stderr */
> #include <unistd.h> /* fork, pipe, read, write */
> #include <sys/poll.h> /* poll */
>
> static void WriteAByte(int fd);
> static void ReadAByte(int fd);
>
> int main(void)
> {
> int pipes[2];
> int pipes2[2];
>
> pipe(pipes);
> pipe(pipes2);
>
> if (0 == fork())
> {
> dup2(pipes[0], 0);
> dup2(pipes2[0], 1);
>
> ReadAByte(0);
> WriteAByte(1);
> }
> else
> {
> WriteAByte(pipes[1]);
> ReadAByte(pipes2[1]);
> }
>
> return (0);
> }
>
> void ReadAByte(int fd)
> {
> struct pollfd fds;
> int res;
> char byte;
>
> fds.fd = fd;
> fds.events = POLLIN;
>
> res = poll(&fds, 1, 100);
> if (res != 0)
> {
> (void)fprintf(stderr,
> ">>%d Got something (%d)<<\n",
> getpid(),
> read(fd, &byte, 1));
> }
> }
>
> void WriteAByte(int fd)
> {
> char byte = 'x';
> (void)fprintf(stderr,
> ">>%d Wrote something (%d)<<\n",
> getpid(),
> write(fd, &byte, 1));
> }
>
> On solaris (5.6 Generic_105181-31 sun4u sparc SUNW,Ultra-2) the
> program works fine:
>
> )<<
>
> On Linux however (2.4.21-15.ELsmp i686 GNU/Linux) write to stdout
> fails with errno 9, Bad file number.
>
>
> Any help/input is appreciated.


How are you checking errno? You need to check it *before* calling
fprintf(), because this function almost always modifies errno (and EBADF
is a common value that it sets it to). So change your code to something
like:

result = write(fd, &byte, 1);
if (result == -1)
perror(">>%d couldn't write something (%d)<<", getpid(), result);
else
(void)fprintf(stderr, ">>%d Wrote something (%d)<<\n",
getpid, result);

--
Barry Margolin, barmar@alum.mit.edu
Arlington, MA
*** PLEASE post questions in newsgroups, not directly to me ***
sean larsson

2004-06-15, 5:57 pm

On Tue, 15 Jun 2004 13:24:26 -0400
Barry Margolin <barmar@alum.mit.edu> wrote:

> In article <6fd342f2.0406150830.31c5413d@posting.google.com>,
> r_holgersson@hotmail.com (Rickard) wrote:
>
>
> How are you checking errno? You need to check it *before* calling
> fprintf(), because this function almost always modifies errno (and EBADF
> is a common value that it sets it to). So change your code to something
> like:
>
> result = write(fd, &byte, 1);
> if (result == -1)
> perror(">>%d couldn't write something (%d)<<", getpid(), result);
> else
> (void)fprintf(stderr, ">>%d Wrote something (%d)<<\n",
> getpid, result);
>
> --
> Barry Margolin, barmar@alum.mit.edu
> Arlington, MA
> *** PLEASE post questions in newsgroups, not directly to me ***


i'm pretty sure the problem is what i said above. he is reopening STDOUT on the read end of a pipe, and then when he writes to STDOUT later he is writing to the read end of the pipe, which is returning EBADF:

/* the function that runs when u write to a read only pipe /linux/fs/pipe.c*/
static ssize_t
bad_pipe_w(struct file *filp, const char *buf, size_t count, loff_t *ppos)
{
return -EBADF;
}


--
-sean
Barry Margolin

2004-06-15, 5:57 pm

In article <20040615161336.70ce1991.infamous42md@ERASEMEhotpop.com>,
sean larsson <infamous42md@ERASEMEhotpop.com> wrote:

> i'm pretty sure the problem is what i said above. he is reopening STDOUT on
> the read end of a pipe, and then when he writes to STDOUT later he is writing
> to the read end of the pipe, which is returning EBADF:


I agree, I hadn't noticed that problem in his code initially.

The reason it's working on Solaris and failing on Linux is because
Solaris's pipes are bidirectional; you can read and write both ends
(essentially, Solaris's pipe() use the same underlying mechanism as
socketpair()). This is not required by POSIX or SUS, and Linux doesn't
do it, so you have to make sure you use the correct ends for each
operation.

--
Barry Margolin, barmar@alum.mit.edu
Arlington, MA
*** PLEASE post questions in newsgroups, not directly to me ***
Kenny McCormack

2004-06-16, 5:57 pm

In article <barmar-89E84C.16302415062004@comcast.dca.giganews.com>,
Barry Margolin <barmar@alum.mit.edu> wrote:
....
>Solaris's pipes are bidirectional; you can read and write both ends
>(essentially, Solaris's pipe() use the same underlying mechanism as
>socketpair()). This is not required by POSIX or SUS, and Linux doesn't
>do it, so you have to make sure you use the correct ends for each
>operation.


Or just use socketpair() instead of pipe(), and be done with it.

Sponsored Links






Free braindumps | Software forum | Database administration forum

Copyright 2003 - 2008 webservertalk.com