From: ahlan@marriott.org
Subject: Gnat Sockets - UDP timeout too short.
Date: Wed, 12 Oct 2016 07:23:37 -0700 (PDT)
Date: 2016-10-12T07:23:37-07:00 [thread overview]
Message-ID: <4a05ca67-2ecc-4907-a817-38071dba832b@googlegroups.com> (raw)
Under Microsoft Windows 8.1 (and later) Gnat.Sockets.Receive_Socket returns too early whilst waiting for a UDP datagram.
In our test program (below) we create a UDP socket, set the timeout for one second, bind it to a port and then call receive on the socket.
We catch and resolve the Socket_Error exception and process the expected Connection_Timed_Out.
We note the time before issuing Receive_Socket and the time when we catch the exception and then compare the elapsed time with the receive timeout.
On Window systems prior to Win8.1 this seems to work as expected, the elapsed time is always greater than the receive timeout.
However under Win8.1 (and later) the call to Receive_Socket returns approximately half a second too early!
Curiously, if I write the same thing using the Win32.WinSock API then it works as expected. Which I find odd because I would have thought that Gnat.Sockets would simply be a series of wrappers around a few WinApi calls. But then what do I know?
The effect of this bug is that programs using UDP protocols timeout earlier than they should do - which often leads to curious behaviour.
We have tested this on a couple of PCs running a variety of flavours of Ms-Windows. So far it seems that XP & Win7 work as expected whereas Win8 and Win10 fail.
Has anyone any idea what might cause this problem and how we might go about fixing it?
Best wishes,
MfG
Ahlan
------------------------------
with Ada.Text_IO;
with Ada.Exceptions;
with Ada.Real_Time;
with Ada.Streams;
with GNAT.Sockets;
package body Test is
package Io renames Ada.Text_IO;
package Net renames GNAT.Sockets;
Receive_Timeout : constant Duration := 1.0;
Receive_Timeout_Span : constant Ada.Real_Time.Time_Span := Ada.Real_Time.To_Time_Span (Receive_Timeout);
procedure Work is
The_Datagram : Ada.Streams.Stream_Element_Array (1..20);
The_Last : Ada.Streams.Stream_Element_Offset;
The_Socket : Net.Socket_Type;
Start_Time : Ada.Real_Time.Time;
End_Time : Ada.Real_Time.Time;
use type Ada.Real_Time.Time;
begin
Net.Create_Socket (Socket => The_Socket,
Family => Net.Family_Inet,
Mode => Net.Socket_Datagram);
Net.Set_Socket_Option (Socket => The_Socket,
Option => (Net.Receive_Timeout, Timeout => Receive_Timeout));
Net.Bind_Socket (The_Socket, (Family => Net.Family_Inet,
Addr => Net.Any_Inet_Addr,
Port => 11154));
loop
begin
Start_Time := Ada.Real_Time.Clock;
Net.Receive_Socket (Socket => The_Socket,
Item => The_Datagram,
Last => The_Last);
Io.New_Line;
Io.Put_Line ("Unexpected reply!");
exit;
exception
when Occurrence: Net.Socket_Error =>
End_Time := Ada.Real_Time.Clock;
declare
Error : constant Net.Error_Type := Net.Resolve_Exception (Occurrence);
use type Net.Error_Type;
begin
if Error = Net.Connection_Timed_Out then
if End_Time >= (Start_Time + Receive_Timeout_Span) then
Io.Put (".");
else
Io.New_Line;
declare
use type Ada.Real_Time.Time_Span;
Shortfall : constant Ada.Real_Time.Time_Span := Receive_Timeout_Span - (End_Time - Start_Time);
begin
Io.Put_Line ("Timeout too short by" & Ada.Real_Time.To_Duration (Shortfall)'img & "seconds");
end;
end if;
else
Io.Put_Line ("Socket_Error : Unexpected error=" & Error'img);
exit;
end if;
end;
when Event : others =>
Io.Put_Line ("Unexpected exception: " & Ada.Exceptions.Exception_Name (Event));
end;
end loop;
exception
when Event : others =>
Io.Put_Line ("Internal Error: " & Ada.Exceptions.Exception_Name (Event));
end Work;
next reply other threads:[~2016-10-12 14:23 UTC|newest]
Thread overview: 2+ messages / expand[flat|nested] mbox.gz Atom feed top
2016-10-12 14:23 ahlan [this message]
2016-11-04 8:48 ` Gnat Sockets - UDP timeout too short ahlan.marriott
replies disabled
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox