comp.lang.ada
 help / color / mirror / Atom feed
* "broken pipe" while reading/writing stream-based sockets
@ 2005-05-10 23:02 fabio de francesco
  2005-05-11 10:46 ` Adrien Plisson
                   ` (2 more replies)
  0 siblings, 3 replies; 12+ messages in thread
From: fabio de francesco @ 2005-05-10 23:02 UTC (permalink / raw)


Ciao,

I'm still having problems while doing sockets read/write. I have a
server that often crashes with error "Broken Pipe". The server works
always with the same clients and many times it doesn't crash until
something happens that I don't understand.

This is the server code:

-- file tcp_server.adb

with GNAT.Sockets;             use GNAT.Sockets;
with Ada.Text_IO;                use Ada.Text_IO;

procedure TCP_Server is

    Socket : Socket_Type;
    Client : Socket_Type;
    Sock_Addr : Sock_Addr_Type;
    Cli_Addr : Sock_Addr_Type;
    L : constant Positive := 5;
    Channel : Stream_Access;
    S : String( 1 .. 80 );

begin

    Initialize;
    Create_Socket( Socket );
    Set_Socket_Option( Socket, Socket_Level, ( Reuse_Address, True ) );
    Sock_Addr.Addr := Inet_Addr( "127.0.0.1" );
    Sock_Addr.Port := 9876;
    Bind_Socket( Socket, Sock_Addr );
    Listen_Socket( Socket, L );
    Put_Line( "Server in attesa di connessioni..." );

    loop
        Accept_Socket( Socket, Client, Cli_Addr );
        Channel := Stream( Client );
        String'Read( Channel, S );
        String'Write ( Channel, ( "Ricevuto " & S ) );
        Put_Line( "Client ha inviato codice """ & S & """" );
        Free( Channel );
        Close_Socket( Client );
        if S( 1 .. 4 ) = "kill" then
            Put_Line( "Sono stato ucciso" );
            exit;
        end if;
    end loop;

    Close_Socket( Socket );
    Finalize;

end TCP_Server;


And the following is client code:

-- file tcp_client.adb

with GNAT.Sockets;             use GNAT.Sockets;
with Ada.Text_IO;                 use Ada.Text_IO;
with Ada.Strings;                  use Ada.Strings;
with Ada.Strings.Fixed;         use Ada.Strings.Fixed;
with Ada.Command_Line;      use Ada.Command_Line;

procedure TCP_Client is

    Socket : Socket_Type;
    Address : Sock_Addr_Type;
    Channel : Stream_Access;
    S : String( 1 .. 80 );

begin

    if Argument_Count < 1 then
        return;
    end if;

    Initialize;
    Create_Socket( Socket );
    Address.Addr := Addresses( Get_Host_By_Name( "localhost" ), 1 );
    Address.Port := 9876;
    Connect_Socket( Socket, Address );
    Channel := Stream( Socket );

    Move( Argument( 1 ), S );
    if S( 1 .. 4 ) = "kill" then
        Put_Line( "Sto ordinando a Server di fermarsi!" );
    else
        Put_Line( "Sto inviando """ & Trim( S, Both ) & """" );
    end if;

    String'Write( Channel, S );
    String'Read( Channel, S );
    Put_Line( "Server ha risposto """ & Trim( S, Both ) & """" );

    Free( Channel );
    Close_Socket( Socket );
    Finalize;

end TCP_Client;


I usually test the server this way:

$ ./tcp_client abc & ./tcp_client def & ./tcp_client xyz & ./tcp_client
kill

1) Why does this server sometimes crash with "Broken Pipe"?
2) It seems that using Input/Output instead of Read/Write never causes
"Broken Pipe". Why?

Thanks to all of you who will reply,

fabio de francesco




^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: "broken pipe" while reading/writing stream-based sockets
  2005-05-10 23:02 "broken pipe" while reading/writing stream-based sockets fabio de francesco
@ 2005-05-11 10:46 ` Adrien Plisson
  2005-05-11 15:01   ` fabio de francesco
  2005-05-11 21:18 ` Simon Wright
  2005-05-14 21:27 ` Florian Weimer
  2 siblings, 1 reply; 12+ messages in thread
From: Adrien Plisson @ 2005-05-11 10:46 UTC (permalink / raw)


fabio de francesco wrote:
> I usually test the server this way:
> 
> $ ./tcp_client abc & ./tcp_client def & ./tcp_client xyz & ./tcp_client
> kill
> 
> 1) Why does this server sometimes crash with "Broken Pipe"?

on my windows machine, i get the windows equivalent ("connection reset 
by peer") on every test.

it seems due to the speed of your computer. i observed that closing a 
local socket (that is a socket which connect a server and a client on 
the same machine) while data are not already received by the other 
side always causes loss of data on fast computers.

-- 
rien



^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: "broken pipe" while reading/writing stream-based sockets
  2005-05-11 10:46 ` Adrien Plisson
@ 2005-05-11 15:01   ` fabio de francesco
  0 siblings, 0 replies; 12+ messages in thread
From: fabio de francesco @ 2005-05-11 15:01 UTC (permalink / raw)



Adrien Plisson wrote:
> fabio de francesco wrote:
> > I usually test the server this way:
> >
> > $ ./tcp_client abc & ./tcp_client def & ./tcp_client xyz &
./tcp_client
> > kill
> >
> > 1) Why does this server sometimes crash with "Broken Pipe"?
>
> on my windows machine, i get the windows equivalent ("connection
reset
> by peer") on every test.

I get the same error as yours on the client side. "Broken Pipe" is only
on server side. We get "connection reset by peer" only after the server
crashes.

>
> it seems due to the speed of your computer. i observed that closing a

> local socket (that is a socket which connect a server and a client on

> the same machine) while data are not already received by the other
> side always causes loss of data on fast computers.
>

I'm not so sure, because I have never seen that "Broken Pipe" error
before now on my computer. Furthermore I don't get any crashes while
running similar client/server Ada programs using T'Input/T'Output or
Receive_Socket/Send_Socket on the same computer.

If it can help in investigating this issue I can post these other
programs too.

As a consequence I must think I am missing something in that specific
code. Please help me to spot what I'm doing wrong.

fabio de francesco




^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: "broken pipe" while reading/writing stream-based sockets
  2005-05-10 23:02 "broken pipe" while reading/writing stream-based sockets fabio de francesco
  2005-05-11 10:46 ` Adrien Plisson
@ 2005-05-11 21:18 ` Simon Wright
  2005-05-11 23:30   ` fabio de francesco
  2005-05-13 20:18   ` fabio de francesco
  2005-05-14 21:27 ` Florian Weimer
  2 siblings, 2 replies; 12+ messages in thread
From: Simon Wright @ 2005-05-11 21:18 UTC (permalink / raw)


"fabio de francesco" <fmdf@tiscali.it> writes:

> I usually test the server this way:
>
> $ ./tcp_client abc & ./tcp_client def & ./tcp_client xyz & ./tcp_client
> kill
>
> 1) Why does this server sometimes crash with "Broken Pipe"?

Just now I replaced your 'kill' above with 'lmn' and ran it 25 times
with no errors -- GCC 4.0.0 on Darwin 7.9.0

--S



^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: "broken pipe" while reading/writing stream-based sockets
  2005-05-11 21:18 ` Simon Wright
@ 2005-05-11 23:30   ` fabio de francesco
  2005-05-13 20:18   ` fabio de francesco
  1 sibling, 0 replies; 12+ messages in thread
From: fabio de francesco @ 2005-05-11 23:30 UTC (permalink / raw)



Simon Wright wrote:
> "fabio de francesco" <fmdf@tiscali.it> writes:
>
> > I usually test the server this way:
> >
> > $ ./tcp_client abc & ./tcp_client def & ./tcp_client xyz &
./tcp_client
> > kill
> >
> > 1) Why does this server sometimes crash with "Broken Pipe"?
>
> Just now I replaced your 'kill' above with 'lmn' and ran it 25 times
> with no errors -- GCC 4.0.0 on Darwin 7.9.0
>
> --S

I compiled the program with GCC 3.4.1 on Linux 2.6.11.5. It continues
to report the same error.

I'm going to bootstrap a brand new GCC 4.0 and then I try again.

fabio de francesco




^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: "broken pipe" while reading/writing stream-based sockets
  2005-05-11 21:18 ` Simon Wright
  2005-05-11 23:30   ` fabio de francesco
@ 2005-05-13 20:18   ` fabio de francesco
  2005-05-13 20:25     ` fabio de francesco
  2005-05-14 20:39     ` Jeffrey Carter
  1 sibling, 2 replies; 12+ messages in thread
From: fabio de francesco @ 2005-05-13 20:18 UTC (permalink / raw)



Simon Wright wrote:
> "fabio de francesco" <fmdf@tiscali.it> writes:
>
> > I usually test the server this way:
> >
> > $ ./tcp_client abc & ./tcp_client def & ./tcp_client xyz &
./tcp_client
> > kill
> >
> > 1) Why does this server sometimes crash with "Broken Pipe"?
>
> Just now I replaced your 'kill' above with 'lmn' and ran it 25 times
> with no errors -- GCC 4.0.0 on Darwin 7.9.0
>
> --S

As I wrote in a previous message I bootstrapped a new GCC 4.0.0 and
then I recompiled those programs again.

The server program continues to crash giving a more elaborated message:

raised GNAT.SOCKETS.SOCKET_ERROR : [32] Broken pipe

The message I got with GCC 3.4.1 was only "Broken Pipe". Now there's
also that "32" number. What is it?

Do any of you have any suggestion on this problem?

Regards,

fabio de francesco




^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: "broken pipe" while reading/writing stream-based sockets
  2005-05-13 20:18   ` fabio de francesco
@ 2005-05-13 20:25     ` fabio de francesco
  2005-05-14 20:39     ` Jeffrey Carter
  1 sibling, 0 replies; 12+ messages in thread
From: fabio de francesco @ 2005-05-13 20:25 UTC (permalink / raw)



fabio de francesco wrote:

>
> As I wrote in a previous message I bootstrapped a new GCC 4.0.0 and
> then I recompiled those programs again.
>
> The server program continues to crash giving a more elaborated
message:
>
> raised GNAT.SOCKETS.SOCKET_ERROR : [32] Broken pipe
>
> The message I got with GCC 3.4.1 was only "Broken Pipe". Now there's
> also that "32" number. What is it?
>
> Do any of you have any suggestion on this problem?
>

Where and how would you generally investigate on a problem like this?

fdf




^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: "broken pipe" while reading/writing stream-based sockets
  2005-05-13 20:18   ` fabio de francesco
  2005-05-13 20:25     ` fabio de francesco
@ 2005-05-14 20:39     ` Jeffrey Carter
  1 sibling, 0 replies; 12+ messages in thread
From: Jeffrey Carter @ 2005-05-14 20:39 UTC (permalink / raw)


fabio de francesco wrote:

> raised GNAT.SOCKETS.SOCKET_ERROR : [32] Broken pipe

One thing you could do is handle Gnat.Sockets.Socket_Error.

-- 
Jeff Carter
"There's no messiah here. There's a mess all right, but no messiah."
Monty Python's Life of Brian
84



^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: "broken pipe" while reading/writing stream-based sockets
  2005-05-10 23:02 "broken pipe" while reading/writing stream-based sockets fabio de francesco
  2005-05-11 10:46 ` Adrien Plisson
  2005-05-11 21:18 ` Simon Wright
@ 2005-05-14 21:27 ` Florian Weimer
  2005-05-20 15:01   ` fabio de francesco
  2 siblings, 1 reply; 12+ messages in thread
From: Florian Weimer @ 2005-05-14 21:27 UTC (permalink / raw)


* fabio de francesco:

> 1) Why does this server sometimes crash with "Broken Pipe"?

This usually indicates that the client closed its end of the
connection while the server was still sending data.  Maybe this
happens because your code does not deal with partial reads/writes.

> 2) It seems that using Input/Output instead of Read/Write never causes
> "Broken Pipe". Why?

The stream implementation provided by GNAT.Sockets deals with partial
reads and writes.



^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: "broken pipe" while reading/writing stream-based sockets
  2005-05-14 21:27 ` Florian Weimer
@ 2005-05-20 15:01   ` fabio de francesco
  2005-05-20 17:52     ` tmoran
  2005-05-20 20:02     ` Simon Wright
  0 siblings, 2 replies; 12+ messages in thread
From: fabio de francesco @ 2005-05-20 15:01 UTC (permalink / raw)



Florian Weimer wrote:
> * fabio de francesco:
>
> > 1) Why does this server sometimes crash with "Broken Pipe"?
>
> This usually indicates that the client closed its end of the
> connection while the server was still sending data.  Maybe this
> happens because your code does not deal with partial reads/writes.
>
> > 2) It seems that using Input/Output instead of Read/Write never
causes
> > "Broken Pipe". Why?
>
> The stream implementation provided by GNAT.Sockets deals with partial
> reads and writes.

In C I know how to read() in a loop and increment a pointer to a buffer
(a C string) while receiving characters until there are no more of
them. It is sufficient that read() returns how many characters has
already read and some little math involving buffer size.

In Ada I don't know how to do it... Can you please give me any
suggestions?

Thank you in advance.

fabio




^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: "broken pipe" while reading/writing stream-based sockets
  2005-05-20 15:01   ` fabio de francesco
@ 2005-05-20 17:52     ` tmoran
  2005-05-20 20:02     ` Simon Wright
  1 sibling, 0 replies; 12+ messages in thread
From: tmoran @ 2005-05-20 17:52 UTC (permalink / raw)


> In C I know how to read() in a loop and increment a pointer to a buffer
> (a C string) while receiving characters until there are no more of
> them. It is sufficient that read() returns how many characters has
> already read and some little math involving buffer size.
>
> In Ada I don't know how to do it... Can you please give me any
> suggestions?
   Buffer : String(a .. b);
   Last : Natural := Buffer'first-1;
begin
   while Last < Buffer'last loop
     read(input_source, Buffer(Last+1 .. Buffer'last), Last);
   end loop;



^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: "broken pipe" while reading/writing stream-based sockets
  2005-05-20 15:01   ` fabio de francesco
  2005-05-20 17:52     ` tmoran
@ 2005-05-20 20:02     ` Simon Wright
  1 sibling, 0 replies; 12+ messages in thread
From: Simon Wright @ 2005-05-20 20:02 UTC (permalink / raw)


"fabio de francesco" <fmdf@tiscali.it> writes:

> Florian Weimer wrote:
>> * fabio de francesco:
>>
>> > 1) Why does this server sometimes crash with "Broken Pipe"?
>>
>> This usually indicates that the client closed its end of the
>> connection while the server was still sending data.  Maybe this
>> happens because your code does not deal with partial reads/writes.
>>
>> > 2) It seems that using Input/Output instead of Read/Write never
> causes
>> > "Broken Pipe". Why?
>>
>> The stream implementation provided by GNAT.Sockets deals with partial
>> reads and writes.
>
> In C I know how to read() in a loop and increment a pointer to a buffer
> (a C string) while receiving characters until there are no more of
> them. It is sufficient that read() returns how many characters has
> already read and some little math involving buffer size.
>
> In Ada I don't know how to do it... Can you please give me any
> suggestions?

I'm sure there's a better way .. but this is what I did

   function Read_Request (From : Socket_Type) return String is
      Tmp : Stream_Element_Array (1 .. 2048);
      Last : Stream_Element_Offset := Tmp'First - 1;
      Next : Stream_Element_Offset;
      Termination : constant Stream_Element_Array :=
        (Character'Pos (CR),
         Character'Pos (LF),
         Character'Pos (CR),
         Character'Pos (LF));
      S : Stream_Access := Stream (From);
   begin

      --  We need to read the whole request from the client. Of course
      --  we don't know how long it is. We can't just issue an
      --  Ada.Streams.Read for a large buffer, because the client may
      --  not have sent that much and if she hasn't we'll block until
      --  she gives up and closes the socket. So we read a character
      --  at a time until we've got the CR/LF/CR/LF which terminates
      --  the line.
      loop
         Ada.Streams.Read (Stream => S.all,
                           Item => Tmp (Last + 1 .. Last + 1),
                           Last => Next);
         exit when Next = Last;
         Last := Last + 1;
         exit when Last >= Termination'Length
           and then Tmp (Last - 3 .. Last) = Termination;
         exit when Last = Tmp'Last;
      end loop;

      Free_Stream (S);

      declare
         Result : String (1 .. Natural (Last));
         pragma Import (Ada, Result);
         for Result'Address use Tmp'Address;
      begin
         return Result;
      end;

   end Read_Request;



^ permalink raw reply	[flat|nested] 12+ messages in thread

end of thread, other threads:[~2005-05-20 20:02 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2005-05-10 23:02 "broken pipe" while reading/writing stream-based sockets fabio de francesco
2005-05-11 10:46 ` Adrien Plisson
2005-05-11 15:01   ` fabio de francesco
2005-05-11 21:18 ` Simon Wright
2005-05-11 23:30   ` fabio de francesco
2005-05-13 20:18   ` fabio de francesco
2005-05-13 20:25     ` fabio de francesco
2005-05-14 20:39     ` Jeffrey Carter
2005-05-14 21:27 ` Florian Weimer
2005-05-20 15:01   ` fabio de francesco
2005-05-20 17:52     ` tmoran
2005-05-20 20:02     ` Simon Wright

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox