select + stderr
Web Server forum
Back To The Forum Home!Search!Private Messaging System

Web Server Talk Web Server Talk > Unix and Linux reviews > Free Unix support > Unix Programming > select + stderr




  Last Thread   Next Thread Next
  Show Printable Version Email this Page Subscribe to this Thread      Post New Thread    Post A Reply      

    select + stderr  
Thomas Beneke


View Ip Address Report This Message To A Moderator Edit/Delete Message


 
01-21-05 07:51 AM

Hi,

I have a client - server, but this works only for stdout. What do I have
to change . If I send a 'ls' to the server, I get the correct response
on the client side. If I send a 'ls /sdfdsfdlfsdl' ( a non existing
file), I get the error message on server side on stderr, but on client
side on stdout.

while (FD_ISSET(sockfd, &rfdset))
{
if (select( fd+1 , &rfdset, NULL, NULL, NULL) < 0) {
if (errno != EINTR) {
fprintf(stderr,"select failed\n");
exit(1);
}
}
if (FD_ISSET(sockfd, &rfdset)) {
if ( (numbytes = recv(sockfd, buffer, sizeof(buf), MSG_WAITALL))
< 0 )
{
fprintf(stderr,"recv failed.\n");
exit(1);
}
if ( numbytes ) {
if ( (write(STDOUT_FILENO, buffer, numbytes)) <0) {
fprintf(stderr,"send stdout failed\n");
exit(1);
}
}
else if (numbytes == 0 || errno != EWOULDBLOCK)
FD_CLR(sockfd, &rfdset);
}
}





[ Post a follow-up to this message ]



    Re: select + stderr  
Jens.Toerring@physik.fu-berlin.de


View Ip Address Report This Message To A Moderator Edit/Delete Message


 
01-21-05 12:48 PM

Thomas Beneke <thomas.beneke@web.de> wrote:
> I have a client - server, but this works only for stdout.

What works? What means stdout in the context of a server-client pair?

>                                               What do I have
> to change . If I send a 'ls' to the server, I get the correct response
> on the client side. If I send a 'ls /sdfdsfdlfsdl' ( a non existing
> file), I get the error message on server side on stderr, but on client
> side on stdout.

> while (FD_ISSET(sockfd, &rfdset))

I don't understand what this is good for - using the FD_ISSET macro
only really makes sense *after* you called select().

> {
>    if (select( fd+1 , &rfdset, NULL, NULL, NULL) < 0) {
>       if (errno != EINTR) {
>          fprintf(stderr,"select failed\n");
>          exit(1);
>        }
>      }
>      if (FD_ISSET(sockfd, &rfdset)) {
>        if ( (numbytes = recv(sockfd, buffer, sizeof(buf), MSG_WAITALL))
> < 0 )

Are you sure the MSG_WAITALL is appropriate here? What is supposd to
happen when the message sent by the server is less than sizeof(buf)
bytes?

>        {
>          fprintf(stderr,"recv failed.\n");
>          exit(1);
>        }
>        if ( numbytes ) {
>          if ( (write(STDOUT_FILENO, buffer, numbytes)) <0) {
>            fprintf(stderr,"send stdout failed\n");
>            exit(1);
>          }
>        }
>        else if (numbytes == 0 || errno != EWOULDBLOCK)

If recv() didn't return -1 the value of errno doesn't tell you anything,
you are never supposed to do anything with errno's value unless an error
happened. If you feel like checking for EWOULDBLOCK (BTW, it could also
be EAGAIN according to SUSv3) you need to do that further up where you
check 'numbytes' for a negative value.

>          FD_CLR(sockfd, &rfdset);

If you call select() with a cleared fdset you tell it to wait for *no*
file descriptors to become ready for reading. I guess you do that because
of the bogus while loop condition at the start. You better make the while
loop an infinite loop (i.e. use "while(1)" and break from it once you find
that you recv() returned 0 (telling you that the other side closed the
socket).

>      }

Before you call select() again you must set up the fdset anew - other-
wise the case that select() did return -1 with errno being set to EINTR
won't be dealt with correctly (or if you're dealing with more than a
single file descriptor you call select() on).

>    }

If I guess correctly that you want to have your client send a shell
command to the server, have the server execute it by fork()ing and
exec()ing a shell and send back both what the server received from
both the stdout and stderr of the shell it spawned separately, then
you need two logical channels between the server and the client -
one for sending back the result from stdout and one for sending what
appeared on stderr. For that you need either two sockets or you must
develop some kind of protocol that allows the client to figure out
what was what. There's nothing magical about stdout and stderr, they
are just two different file descriptor - and when you have the server
send what it read from both these channels intermixed via a single
channel to the client, the client won't be able to untangle them.

The simplest solution is probably to open two sockets and have the
server write what it got from the stdout of the shell via one of the
sockets and what it read from stderr of the shell to the other one.
The client then listens on both these sockets, writing out what it
receives from the first one to its stdout and what it receives from
the second one to its stderr.
Regards, Jens

PS: I hope you're aware of the security implications of such a server
running on your machine and have access to that server secured by a
password (which you better don't send unencrypted over the net!).
--
\   Jens Thoms Toerring  ___  Jens.Toerring@physik.fu-berlin.de
\__________________________  http://www.toerring.de





[ Post a follow-up to this message ]



    Re: select + stderr  
Jens.Toerring@physik.fu-berlin.de


View Ip Address Report This Message To A Moderator Edit/Delete Message


 
01-21-05 10:52 PM

Thomas Beneke <thomas.beneke@web.de> wrote:
> Now I've added on client a second socket()

> errfd = socket(AF_INET, SOCK_STREAM, 0)

> a second connect()

> connect(errfd, (struct sockaddr *)&server, sizeof(struct sockaddr))

> and a FD_ISSET for errfd

> if (FD_ISSET(errfd, &rfdset)) {
>     if ( (numbytes = read(errfd, buffer, sizeof(buf))) <= 0 )
> .

> On my server i've added a second getpeername()

> getpeername(err_fd, (struct sockaddr *)&client, &client_len)

No idea what you need that for...

> the pipe(), fork() and exec()

> if (pipe(pipe_out) == -1 || pipe(pipe_err) == -1 )
>     exit;

>    switch (fork()) {
>          case -1:
>                  fprintf(stderr, "fork failed.\n");
>                  _exit(1);

>          case 0:
>                  /* child */

>                   /* stdout. */
>                  close(pipe_out[0]);
>                  if (dup2(pipe_out[1], 1) == -1)

It's probably better to write 'STDOUT_FILENO' instead of using the
number 1 here since it's easier to recognnize.

>                     fprintf(stderr, "aasapd: dup2(pipe_out).\n");
>                  close(pipe_out[1]);

>                  /* stderr. */
>                  close(pipe_err[0]);
>                  if (dup2(pipe_err[1], 2) == -1)

And here 'STDERR_FILENO'.

>                     fprintf(stderr, "aasapd: dup2(pipe_err).\n");
>                  close(pipe_err[1]);

>                  execl("/bin/sh", "sh", "-c", buffer, (char *) 0);
>                  _exit(1);
>          default:
>          default:
>                  /* parent */
>          close(pipe_out[1]);
>          close(pipe_err[1]);
>    }

> /* only for test */
>   numbytes = read(pipe_err[0], buffer, sizeof(buf));
>    write(err_fd, buffer, numbytes);
>   numbytes = read(pipe_out[0], buffer, sizeof(buf));
>    write(client_fd, buffer, numbytes);

> The Problem now is that both outputs using stdin on my client. Why ?

What does that sentence mean? What is "both" and what means "outputs
using stdin"? On the client side what you get from client_fd should
be the stdout of the command the server did run for you and from
err_fd what it got from stderr. If you write that out in your client
you of course have to write what you got from client_fd to the clients
stdout and what you got from err_fd to its stderr file descriptor.

Regards, Jens
--
\   Jens Thoms Toerring  ___  Jens.Toerring@physik.fu-berlin.de
\__________________________  http://www.toerring.de





[ Post a follow-up to this message ]



    Re: select + stderr  
Thomas Beneke


View Ip Address Report This Message To A Moderator Edit/Delete Message


 
01-21-05 10:52 PM

Jens.Toerring@physik.fu-berlin.de wrote:
> Thomas Beneke <thomas.beneke@web.de> wrote:
> 
>
> 
>
> 
>
> 
>
> 
>
> 
>
> 
>
> 
>
>
> No idea what you need that for...
>
> 
>
> 
>
> 
>
> 
>
> 
>
>
> It's probably better to write 'STDOUT_FILENO' instead of using the
> number 1 here since it's easier to recognnize.
>
> 
>
> 
>
>
> And here 'STDERR_FILENO'.
>
> 
>
> 
>
> 
>
> 
>
>
> What does that sentence mean? What is "both" and what means "outputs
> using stdin"? On the client side what you get from client_fd should
> be the stdout of the command the server did run for you and from
> err_fd what it got from stderr. If you write that out in your client
> you of course have to write what you got from client_fd to the clients
> stdout and what you got from err_fd to its stderr file descriptor.
>
>                                     Regards, Jens
Hi Jens,

if I trace the server I see the normal output is send to 1(STDOUT) and
the error message is send to 2(STDERR). But on the client I get both on
the same fd in my select().

Regards,
Thomas





[ Post a follow-up to this message ]



    Re: select + stderr  
Jens.Toerring@physik.fu-berlin.de


View Ip Address Report This Message To A Moderator Edit/Delete Message


 
01-21-05 10:52 PM

Thomas Beneke <thomas.beneke@web.de> wrote:
> if I trace the server I see the normal output is send to 1(STDOUT) and
> the error message is send to 2(STDERR).

Now you have me completely confused. As far as I understood until now
you intended to write what the shell did pass via its stdout to the
server through one socket to the client and what the server got from
the stderr of the shell would be copied to the other socket. Now you
suddenly write the server is sending stuff to stdout and stderr and
there's no mentioning of sockets anymore...

> But on the client I get both on the same fd in my select().

And now we're back to sockets... Do you use different ports for
the socket you send the stdout stuff to and for the other one
via which you send the stderr data?

Regards, Jens
--
\   Jens Thoms Toerring  ___  Jens.Toerring@physik.fu-berlin.de
\__________________________  http://www.toerring.de





[ Post a follow-up to this message ]



    Re: select + stderr  
Thomas Beneke


View Ip Address Report This Message To A Moderator Edit/Delete Message


 
01-21-05 10:52 PM

Jens.Toerring@physik.fu-berlin.de wrote:
> Thomas Beneke <thomas.beneke@web.de> wrote:
> 
>
>
> Now you have me completely confused. As far as I understood until now
> you intended to write what the shell did pass via its stdout to the
> server through one socket to the client and what the server got from
> the stderr of the shell would be copied to the other socket. Now you
> suddenly write the server is sending stuff to stdout and stderr and
> there's no mentioning of sockets anymore...
>
> 
>
>
> And now we're back to sockets... Do you use different ports for
> the socket you send the stdout stuff to and for the other one
> via which you send the stderr data?
>
>                                   Regards, Jens
Hi Jens,

sorry about the confusion. I use the same ports for both directions.

everthing is fine ('ls /root')
<SNIP>
3927  select(5, [3 4], NULL, NULL, NULL) = 1 (in [3])
3927  read(3,
"Desktop\nblfs.txt\nc_samples\ngew_bereitschaft.txt\ngew_route.sh\nlinux_dis
k.txt\nminicom.log\nplatin.ini\nsapgui.png\nsapmsg.ini\nsaproute.ini\nstarof
fice7\nwebsite\n",
1024) = 154
3927  write(1,
"Desktop\nblfs.txt\nc_samples\ngew_bereitschaft.txt\ngew_route.sh\nlinux_dis
k.txt\nminicom.log\nplatin.ini\nsapgui.png\nsapmsg.ini\nsaproute.ini\nstarof
fice7\nwebsite\n",
154) = 154
3927  select(5, [3 4], NULL, NULL, NULL) = 1 (in [3])
3927  read(3, "", 1024)                 = 0
3927  close(3)                          = 0
3927  close(4)                          = 0
</SNIP>

something wrong ('ls /dfdddfd'  #a non existing file)
<SNIP>
3934  select(5, [3 4], NULL, NULL, NULL) = 1 (in [3])
3934  read(3, "ls: ", 1024)             = 4
3934  write(1, "ls: ", 4)               = 4
3934  select(5, [3 4], NULL, NULL, NULL) = 1 (in [3])
3934  read(3, "", 1024)                 = 0
3934  close(3)                          = 0
3934  close(4)                          = 0
</SNIP>

The output of the second trace reads the client from fd 3 (STDOUT from
server) instead of fd 4 (STDERR from server).

--------------------------------------------------

The trace on the server
for ('ls')
3968  mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS,
-1, 0) = 0xb7e92000
3968  write(1,
"Desktop\nblfs.txt\nc_samples\ngew_bereitschaft.txt\ngew_route.sh\nlinux_dis
k.txt\nminicom.log\
nplatin.ini\nsapgui.png\nsapmsg.ini\nsaproute.ini\nstaroffice7\nwebsite\n",
154) = 154
3968  close(1)                          = 0
3968  munmap(0xb7e92000, 4096)          = 0
3968  exit_group(0)                     = ?
3966  <... read resumed> "", 1024)      = 0
3966  write(2, "", 0)                   = 0
3966  read(4,
"Desktop\nblfs.txt\nc_samples\ngew_bereitschaft.txt\ngew_route.sh\nlinux_dis
k.txt\nminicom.log\n
platin.ini\nsapgui.png\nsapmsg.ini\nsaproute.ini\nstaroffice7\nwebsite\n",
1024) = 154
3966  write(0,
"Desktop\nblfs.txt\nc_samples\ngew_bereitschaft.txt\ngew_route.sh\nlinux_dis
k.txt\nminicom.log\
nplatin.ini\nsapgui.png\nsapmsg.ini\nsaproute.ini\nstaroffice7\nwebsite\n",
154) = 154
3966  wait4(-1, NULL, 0, NULL)          = 3968

for ('ls /ddddddd')3976  write(2, "ls: ", 4 <unfinished ...>
3974  <... read resumed> "ls: ", 1024)  = 4
3974  write(2, "ls: ", 4)               = 4
3974  read(4,  <unfinished ...>
3976  <... write resumed> )             = 4
3976  write(2, "/ddddddd", 8)           = 8
3976  write(2, ": No such file or directory", 27) = 27
3976  write(2, "\n", 1)                 = 1
3976  exit_group(1)                     = ?
3974  <... read resumed> "", 1024)      = 0
3974  write(0, "", 0)                   = 0

And here goes something wrong, but I dont no why.

Regards,
Thomas








[ Post a follow-up to this message ]



    Re: select + stderr  
Jens.Toerring@physik.fu-berlin.de


View Ip Address Report This Message To A Moderator Edit/Delete Message


 
01-21-05 10:52 PM

Thomas Beneke <thomas.beneke@web.de> wrote:
> sorry about the confusion. I use the same ports for both directions.

I didn't ask about "directions", I asked if you use two sockets with
_different_ ports for the two channels to the client. If not try that.

> everthing is fine ('ls /root')
> <SNIP>
> 3927  select(5, [3 4], NULL, NULL, NULL) = 1 (in [3])
> 3927  read(3,
> "Desktop\nblfs.txt\nc_samples\ngew_bereitschaft.txt\ngew_route.sh\nlinux_d
isk.txt\nminicom.log\nplatin.ini\nsapgui.png\nsapmsg.ini\nsaproute.ini\nstar
office7\nwebsite\n",
> 1024) = 154
> 3927  write(1,
> "Desktop\nblfs.txt\nc_samples\ngew_bereitschaft.txt\ngew_route.sh\nlinux_d
isk.txt\nminicom.log\nplatin.ini\nsapgui.png\nsapmsg.ini\nsaproute.ini\nstar
office7\nwebsite\n",
> 154) = 154
> 3927  select(5, [3 4], NULL, NULL, NULL) = 1 (in [3])
> 3927  read(3, "", 1024)                 = 0
> 3927  close(3)                          = 0

Ok, the data from the successfull call of 'ls' come in via file
desciptor 3.

> 3927  close(4)                          = 0
> </SNIP>

> something wrong ('ls /dfdddfd'  #a non existing file)
> <SNIP>
> 3934  select(5, [3 4], NULL, NULL, NULL) = 1 (in [3])
> 3934  read(3, "ls: ", 1024)             = 4
> 3934  write(1, "ls: ", 4)               = 4
> 3934  select(5, [3 4], NULL, NULL, NULL) = 1 (in [3])
> 3934  read(3, "", 1024)                 = 0
> 3934  close(3)                          = 0
> 3934  close(4)                          = 0
> </SNIP>

> The output of the second trace reads the client from fd 3 (STDOUT from
> server) instead of fd 4 (STDERR from server).

So there's a problem - probably the other side didn't stuff things into
the appropriate socket.

> The trace on the server
> for ('ls')

> 3968  mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS,
> -1, 0) = 0xb7e92000
> 3968  write(1,
> "Desktop\nblfs.txt\nc_samples\ngew_bereitschaft.txt\ngew_route.sh\nlinux_d
isk.txt\nminicom.log\
> nplatin.ini\nsapgui.png\nsapmsg.ini\nsaproute.ini\nstaroffice7\nwebsite\n"
,
> 154) = 154
> 3968  close(1)                          = 0
> 3968  munmap(0xb7e92000, 4096)          = 0
> 3968  exit_group(0)                     = ?

This seems to be the end of ls...

> 3966  <... read resumed> "", 1024)      = 0
> 3966  write(2, "", 0)                   = 0
> 3966  read(4,
> "Desktop\nblfs.txt\nc_samples\ngew_bereitschaft.txt\ngew_route.sh\nlinux_d
isk.txt\nminicom.log\n
> platin.ini\nsapgui.png\nsapmsg.ini\nsaproute.ini\nstaroffice7\nwebsite\n",
> 1024) = 154
> 3966  write(0,
> "Desktop\nblfs.txt\nc_samples\ngew_bereitschaft.txt\ngew_route.sh\nlinux_d
isk.txt\nminicom.log\
> nplatin.ini\nsapgui.png\nsapmsg.ini\nsaproute.ini\nstaroffice7\nwebsite\n"
,
> 154) = 154
> 3966  wait4(-1, NULL, 0, NULL)          = 3968

You keep me guessing: is 0 the file descriptor for one of the sockets?
Without knowing what the file descriptors stand for I can hardly gues
what might go wrong. Why not post the source code instead of heavily
snipped strace output?

> for ('ls /ddddddd')3976  write(2, "ls: ", 4 <unfinished ...>
> 3974  <... read resumed> "ls: ", 1024)  = 4
> 3974  write(2, "ls: ", 4)               = 4
> 3974  read(4,  <unfinished ...>
> 3976  <... write resumed> )             = 4
> 3976  write(2, "/ddddddd", 8)           = 8
> 3976  write(2, ": No such file or directory", 27) = 27
> 3976  write(2, "\n", 1)                 = 1
> 3976  exit_group(1)                     = ?

Looks like ls is done...

> 3974  <... read resumed> "", 1024)      = 0
> 3974  write(0, "", 0)                   = 0

Where is the part were you write to the socket? I just see a single write
of 0 bytes to 0 (all the rest seems more like something coming from 'ls'),
not even something getting actually read from the output of ls.

Just a question: did you switch from the fork/dup2/execl to using popen()?
In that case all this wouldn't be astonishing since with popen() you can't
get stdout and stderr separately...

Regards, Jens
--
\   Jens Thoms Toerring  ___  Jens.Toerring@physik.fu-berlin.de
\__________________________  http://www.toerring.de





[ Post a follow-up to this message ]



    Re: select + stderr  
Barry Margolin


View Ip Address Report This Message To A Moderator Edit/Delete Message


 
01-22-05 07:48 AM

In article <35cu4hF4kv73tU1@uni-berlin.de>,
Jens.Toerring@physik.fu-berlin.de wrote:

> Just a question: did you switch from the fork/dup2/execl to using popen()?
> In that case all this wouldn't be astonishing since with popen() you can't
> get stdout and stderr separately...

Actually, when you use popen() you can't get stderr at all, it only
redirects stdout.  You can only get stdout if the command line includes
2>&1, which explicitly merges stderr with stdout.

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





[ Post a follow-up to this message ]



    Re: select + stderr  
Thomas Beneke


View Ip Address Report This Message To A Moderator Edit/Delete Message


 
01-24-05 12:47 PM

Jens.Toerring@physik.fu-berlin.de wrote:
> Thomas Beneke <thomas.beneke@web.de> wrote:
> 
>
>
> I didn't ask about "directions", I asked if you use two sockets with
> _different_ ports for the two channels to the client. If not try that.
>
> 
>
>
> Ok, the data from the successfull call of 'ls' come in via file
> desciptor 3.
>
> 
>
> 
>
> 
>
>
> So there's a problem - probably the other side didn't stuff things into
> the appropriate socket.
>
> 
>
> 
>
>
> This seems to be the end of ls...
>
> 
>
>
> You keep me guessing: is 0 the file descriptor for one of the sockets?
> Without knowing what the file descriptors stand for I can hardly gues
> what might go wrong. Why not post the source code instead of heavily
> snipped strace output?
>
> 
>
>
> Looks like ls is done...
>
> 
>
>
> Where is the part were you write to the socket? I just see a single write
> of 0 bytes to 0 (all the rest seems more like something coming from 'ls'),
> not even something getting actually read from the output of ls.
>
> Just a question: did you switch from the fork/dup2/execl to using popen()?
> In that case all this wouldn't be astonishing since with popen() you can't
> get stdout and stderr separately...
>
>                                     Regards, Jens
Hi Jens,

I didn't switch to using popen(). Over the weekend I tried to find a
solution for my problem but I didn't find.

Regards,
Thomas





[ Post a follow-up to this message ]



    Sponsored Links  




 





   All times are GMT. The time now is 08:25 PM.      Post New Thread    Post A Reply      
  Last Thread   Next Thread Next


Most Popular forums 

Forum Jump:
Rate This Thread:

Forum Rules:
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts
HTML code is OFF
vB code is ON
Smilies are ON
[IMG] code is OFF
 
Medical and Health forum | Computer Games Reviews | Graphics design forum

Back To The Top
Home | Usercp | Faq | Register