WSAGetLastError returns 0 when it shouldn't but I cannot see why

classic Classic list List threaded Threaded
14 messages Options
Reply | Threaded
Open this post in threaded view
|

WSAGetLastError returns 0 when it shouldn't but I cannot see why

Luca Olivetti-2
Hello, before reporting a bug, I'm asking for support here since I'm not
sure I doing something wrong (and if so what am I doing wrong).

While using synapse in a thread, I saw that it didn't report an error on
connection, eventually I saw that the call to WSAGetLastError was
returning 0 even if it couldn't connect and the connect call returned an
error.
I found bug 10205 (http://bugs.freepascal.org/view.php?id=10205) but in
my case there is no direct writeln in sight (side note: why isn't it
possible to add a note to a closed bug?).

Oddly enough, a slightly modified threadwsagetlast (attached as
project3.lpr) from the one in the bug report works as expected, while my
thread (now using directly the sockets unit, not wrapped by synapse)
still reports 0.

The attached project2.lpr has a connection to a non existent host/port
in a thread and outside the thread, and it both cases it reports 0
(UseSynchronize true or false doesn't make a difference), and while
reduced to the minimum it has the same structure of the thread I'm
actually going to use.
project3.lpr is adapted from the bug report and correctly reports 10060
(connection timed out), but I cannot really see the difference between
one and the other (besides the fact that mine uses methods and the other
uses procedures defined outside the class, but that shouldn't really
matter, should it?)
Note that project3 uses deprecated sockets procedures, while mine uses
the "correc" fp prefixed ones, but I tried with the deprecated ones
before with the same result.

This is under windows with fpc 2.2.0 (coming from a lazarus snapshot),
the original problem with synapse was with a lazarus snapshot with 2.2.1
(hence I went back to 2.2.0 to see if it was a regression in 2.2.1).

Bye
--
Luca


program project2;

{$mode objfpc}{$H+}

uses
  sockets, Classes;

type
  { TInlineSocketThread }

  TNotifyError = procedure (m:string;n:integer) of object;

  TSocketThread = class(TThread)
  private
    FAddress:string;
    FPort:integer;
    FErrMessage:string;
    FErrNum:integer;
    FUseSynchronize:boolean;
    FFinished:boolean;
    FOnError:TNotifyError;
    procedure SyncProcError;
    procedure ErrMsg(m:string;n:integer);
  public
    constructor Create(Address:string; Port:integer; UseSynchronize:boolean);
    destructor Destroy;override;
    procedure Execute;override;
    property OnError:TNotifyError read FOnError write FOnError;
    property Finished:boolean read FFinished;
  end;

{ TSocketThread }

procedure TSocketThread.SyncProcError;
begin
  if Assigned(FOnError) then FOnError(FErrMessage,FErrNum);
end;

procedure TSocketThread.ErrMsg(m: string;n:integer);
begin
  if not Assigned(FOnError) then exit;
  FErrMessage:=m;
  FErrNum:=n;
  if FUseSynchronize then Synchronize(@SyncProcError) else SyncProcError;
end;


constructor TSocketThread.Create(Address:string; Port:integer; UseSynchronize: boolean);
begin
  FAddress:=Address;
  FPort:=Port;
  FUseSynchronize:=UseSynchronize;
  inherited create(true); //create suspended
end;

destructor TSocketThread.Destroy;
begin
  terminate;
  while not FFinished do
      CheckSynchronize(100);
  inherited Destroy;
end;

procedure TSocketThread.Execute;
var s:LongInt;
    SAddr:TInetSockAddr;
    Connected:boolean;
  procedure PError(msg:string);
  var e:integer;
  begin
    e:=SocketError;
    if Connected then fpShutdown(s,2);
    CloseSocket(s);
    Connected:=false;
    ErrMsg(msg,e);
  end;
begin
  Connected:=false;
  S:=fpSocket(AF_INET,SOCK_STREAM,0);
  if SocketError=0 then
  begin
     SAddr.sin_family:=AF_INET;
     Saddr.sin_port:=htons(FPort);
     SAddr.sin_addr.s_addr:=StrToNetAddr(FAddress).s_addr;
     if fpconnect(S,@SAddr,SizeOf(SAddr))=0 then
       Connected:=true else
       PError('connect');
  end;
  if Connected then fpShutdown(s,2);
  CloseSocket(s);
  FFinished:=True;
end;

procedure SocketNoThread(FAddress:string;FPort:integer);
var s:LongInt;
    SAddr:TInetSockAddr;
    Connected:boolean;
  procedure PError(msg:string);
  var e:integer;
  begin
    e:=SocketError;
    if Connected then fpShutdown(s,2);
    CloseSocket(s);
    Connected:=false;
    Writeln(msg,' ',e);
  end;
begin
  Connected:=false;
  S:=fpSocket(AF_INET,SOCK_STREAM,0);
  if SocketError=0 then
  begin
     SAddr.sin_family:=AF_INET;
     Saddr.sin_port:=htons(FPort);
     SAddr.sin_addr.s_addr:=StrToNetAddr(FAddress).s_addr;
     if fpconnect(S,@SAddr,SizeOf(SAddr))=0 then
       Connected:=true else
       PError('connect');
  end;
  if Connected then fpShutdown(s,2);
  CloseSocket(s);
end;

{ TTest }
type
TTest=class
  FSocketThread:TsocketThread;
  procedure SockError(m:string;n:integer);
  constructor Create;
  destructor Destroy;override;
end;

{ TTest }

procedure TTest.SockError(m: string;n:integer);
begin
  writeln(m,' ',n);
end;

constructor TTest.Create;
begin
  FSocketThread:=TSocketThread.Create('1.2.3.4',1000,true);
  FSocketThread.OnError:=@SockError;
  FSocketThread.Resume;
  writeln('Thread started');
end;

destructor TTest.Destroy;
begin
  FSocketThread.Free;
  inherited Destroy;
end;


var Test:TTest;
begin
   Writeln('begin');
   Test:=TTest.Create;
   while not Test.FSocketThread.Finished do CheckSynchronize(100);
   Writeln('thread finished');
   Writeln('Not in a thread');
   SocketNoThread('1.2.3.4',1000);
end.


program test; {$mode objfpc} {$H+}

uses sockets, sysutils, classes;



procedure perror (const s: string);
var e:integer;
begin
  // if cannot bind to port 80, should report 10048
  e:=SocketError;
  writeln ('ERROR: ', S, e);
end;

procedure socktest;
var
  S        : Longint;
  SAddr    : TInetSockAddr;
begin
  S:=Socket (AF_INET,SOCK_STREAM,0);
  if SocketError<>0 then Perror ('Socket : ');
  SAddr.sin_family:=AF_INET;
  { port 80 in network order }
  SAddr.sin_port:=htons(2000);
  SAddr.sin_addr.s_addr:=StrToNetAddr('1.2.3.4').s_addr;
  if not sockets.Connect(S,SAddr,sizeof(saddr)) then PError ('Connect : ') else Writeln('Connected!');
end;

type

{ TTestThread }

TTestThread = class(TThread)
public
 Finished:boolean;
 procedure execute;override;
end;

{ TTestThread }

procedure TTestThread.execute;
begin
  SockTest;
  Finished:=true;
end;


procedure threadtest;
var t:array[1..3] of TTestThread;
    i:integer;
    finito:boolean;
begin
  for i:=1 to 3 do
  begin
   T[i]:=TTestThread.Create(false);
   writeln('Thread ',i,' created');
   sleep(1000);
  end;
  finito:=false;
  while not finito do
  begin
    finito:=true;
    for i:=1 to 3 do finito:=finito and t[i].finished;
  end;
end;

begin
  writeln;
  writeln('Testing WSAGetLastError inside thread...');
  writeln;
  ThreadTest(); // comment this line out and you do get 10048 further below
end.

_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
L-9
Reply | Threaded
Open this post in threaded view
|

Re: WSAGetLastError returns 0 when it shouldn't but I cannot see why

L-9
 > While using synapse in a thread, I saw that it didn't report an error
on connection,
 > eventually I saw that the call to WSAGetLastError was returning 0
even if it couldn't
 > connect and the connect call returned an error.

I am also working on this issue still.

I had the WSAGetLastError working using direct sockets.pp calls but
didn't get it working using synapse yet.. but I didn't try very hard and
that is one of my tasks this week. I think there is something in synapse
possibly which still may be causing the issue, such as maybe
wsagetlasterror not being stored in a temporary variable.. but I think
it is and will have to cheeck (i.e. maybe similar to the writeln issue
where writeln doesn't store it in tmp var first).


 >  I found bug 10205 (http://bugs.freepascal.org/view.php?id=10205) but
in my case
 > there is no direct writeln in sight (side note: why isn't it possible
to add a note
 > to a closed bug?).

PHP blows. Pasta Home page. But no one has written a better solution ;-)
_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Re: WSAGetLastError returns 0 when it shouldn't but I cannot see why

Luca Olivetti-2
El Wed, 27 Feb 2008 12:04:22 -0700
L <[hidden email]> escribió:

>  > While using synapse in a thread, I saw that it didn't report an
>  > error
> on connection,
>  > eventually I saw that the call to WSAGetLastError was returning 0
> even if it couldn't
>  > connect and the connect call returned an error.
>
> I am also working on this issue still.
>
> I had the WSAGetLastError working using direct sockets.pp calls but
> didn't get it working using synapse yet.. but I didn't try very hard
> and that is one of my tasks this week. I think there is something in
> synapse possibly which still may be causing the issue, such as maybe
> wsagetlasterror not being stored in a temporary variable.. but I
> think it is and will have to cheeck (i.e. maybe similar to the
> writeln issue where writeln doesn't store it in tmp var first).

I don't think that synapse is to blame[*]: my test
program is also using the sockets unit directly, and stores SocketError
(which just calls WSAGetLastError) in a variable.
What really puzzles me is that project3 (your test program modified to
use tthread and to do a connect instead of a bind) works while project2
doesn't. Maybe I've been staring at them for too long, but I cannot see
the difference.


[*]apart that you can only know that a socket operation was
successful by checking LastError.

Bye
--
Luca
_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: WSAGetLastError returns 0 when it shouldn't but I cannot see why

Marco van de Voort
In reply to this post by Luca Olivetti-2
> Hello, before reporting a bug, I'm asking for support here since I'm not
> sure I doing something wrong (and if so what am I doing wrong).

I can't test easily atm, but trying killing off socketerror and the older
calls without fp.  Try also to move the "write (thread created)" after the
sleep.
_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: WSAGetLastError returns 0 when it shouldn't but I cannot see why

Luca Olivetti-2
En/na Marco van de Voort ha escrit:
>> Hello, before reporting a bug, I'm asking for support here since I'm not
>> sure I doing something wrong (and if so what am I doing wrong).
>
> I can't test easily atm, but trying killing off socketerror and the older
> calls without fp.  Try also to move the "write (thread created)" after the
> sleep.

Your remarks are about the working example (project3). The non working
one already uses the fp calls, but it still uses SocketError (what
should be its replacement? anyway I saw that it just wraps WSAGetLastError).

Bye
--
Luca

_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
L-9
Reply | Threaded
Open this post in threaded view
|

Re: WSAGetLastError returns 0 when it shouldn't but I cannot see why

L-9
In reply to this post by L-9
Luca wrote:

> I don't think that synapse is to blame[*]: my test
> program is also using the sockets unit directly, and stores SocketError
> (which just calls WSAGetLastError) in a variable.



Found the problem using my brute force writeln('') skills. It is an
issue with freepascal's stack or something to do with buggy threads
methinks. As it is when you call lasterror within another procedure with
local variables.. they are corrupted or something.

procedure PError(msg:string);
var e:integer;
begin
  e:=SocketError;
  writeln('PError: '+ msg, ' ', e);
end;

procedure TSocketThread.Execute;
var s:LongInt;
    SAddr:TInetSockAddr;
    Connected:boolean;
    e: integer;
begin
  Connected:=false;
  S:=fpSocket(AF_INET,SOCK_STREAM,0);
  Perror('Socket issue?');
  e:= socketerror;
  if e > -1 then
  begin
    SAddr.sin_family:=AF_INET;
    Saddr.sin_port:=htons(FPort);
    SAddr.sin_addr.s_addr:=StrToNetAddr(FAddress).s_addr;
    if fpconnect(S,@SAddr,SizeOf(SAddr))=0 then Connected:=true;
    e:=SocketError;
    Writeln('Fuck: ',e);    
    PError('Connect issue'); // THIS RESETS LASTERR, IT SHOULD NOT
  end else writeln('fpsocket issue');
  if Connected then fpShutdown(s,2);
  CloseSocket(s);
  FFinished:=True;
end;

_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
L-9
Reply | Threaded
Open this post in threaded view
|

Re: WSAGetLastError returns 0 when it shouldn't but I cannot see why

L-9
L wrote:

> Luca wrote:
>
>> I don't think that synapse is to blame[*]: my test
>> program is also using the sockets unit directly, and stores SocketError
>> (which just calls WSAGetLastError) in a variable.
>
>
>
> Found the problem using my brute force writeln('') skills. It is an
> issue with freepascal's stack or something to do with buggy threads
> methinks. As it is when you call lasterror within another procedure
> with local variables.. they are corrupted or something.
>
Aha.. I changed the by Value parameter to a CONST parameter in the error
procedure (Perror).. And this solves the issue..

So something to do with calling by Value within a thread versus a const
(pointer?).

I will attach the problem in the bug report previously opened if I can
reopen it.
_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
L-9
Reply | Threaded
Open this post in threaded view
|

Re: WSAGetLastError returns 0 when it shouldn't but I cannot see why

L-9
L wrote:
> Aha.. I changed the by Value parameter to a CONST parameter in the
> error procedure (Perror).. And this solves the issue..
>
> So something to do with calling by Value within a thread versus a
> const (pointer?).
>
> I will attach the problem in the bug report previously opened if I can
> reopen it.
>

http://bugs.freepascal.org/view.php?id=10205

Attached program with problem.

This may be why WriteLn(WsaGetLastError) was causing problems, if
writeln calls a by value parameter too.


_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Re: WSAGetLastError returns 0 when it shouldn't but I cannot see why

Luca Olivetti-2
In reply to this post by L-9
En/na L ha escrit:

>> Found the problem using my brute force writeln('') skills. It is an
>> issue with freepascal's stack or something to do with buggy threads
>> methinks. As it is when you call lasterror within another procedure
>> with local variables.. they are corrupted or something.
>>
> Aha.. I changed the by Value parameter to a CONST parameter in the error
> procedure (Perror).. And this solves the issue..
>
> So something to do with calling by Value within a thread versus a const
> (pointer?).

This seriously worries me, since I use threads extensively, and I mostly
use call by value parameters.

Bye
--
Luca

_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
L-9
Reply | Threaded
Open this post in threaded view
|

Re: WSAGetLastError returns 0 when it shouldn't but I cannot see why

L-9
In reply to this post by L-9
 > This seriously worries me, since I use threads extensively, and I
mostly use call by value
 > parameters.

>
> Bye
> --
> Luca

I use CONST parameters wherever possible for strings.. so that:
1) if I ever port the code to a DLL it is safer (can cast pchar in)
2) const is a stricter contract
3) performance (ha,  premature optimization, by val could be faster sometimes)

As for threads.. I hate them. Wherever there is an alternative solution, I use it. Even if the compiler is working okay, threads still suck. For example I don't give a hoot about a threaded ISAPI server being supposedly more performance oriented than CGI - as if performance makes a difference when the program with threads is buggy. A performance friendly buggy program is about as useless as a demented cheetah that smashes into trees every 3 meters. However, with Sockets programming and blocking sockets... threads are unfortunately one known way of handling the blocking socket.. so.. what to do. LNet? Dunno, Haven't tried it much.. have to try it sometime though ;-)


_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Re: WSAGetLastError returns 0 when it shouldn't but I cannot see why

Luca Olivetti-2
In reply to this post by Luca Olivetti-2
En/na Luca Olivetti ha escrit:

> En/na L ha escrit:
>
>>> Found the problem using my brute force writeln('') skills. It is an
>>> issue with freepascal's stack or something to do with buggy threads
>>> methinks. As it is when you call lasterror within another procedure
>>> with local variables.. they are corrupted or something.
>>>
>> Aha.. I changed the by Value parameter to a CONST parameter in the
>> error procedure (Perror).. And this solves the issue..
>>
>> So something to do with calling by Value within a thread versus a
>> const (pointer?).
>
> This seriously worries me, since I use threads extensively, and I mostly
> use call by value parameters.
I finally had time to test this (do you remember that dilber strip where
he asks his PHB which one of the 3 projects he's juggling should be
finished on schedule, and the PHB replies he should finish them all on
schedule? well, I'm pretty much in the same situation now).
Changing my "procedure PError(msg:string)" to "procedure PError(const
msg:string)" in TSocketThread.Execute in project2 also fixes the problem.
This smells like a bug somewhere in fpc/rtl, since I don't think it
should make a difference.
Anyway, this gives me no clue on how to "fix" synapse.
Synapse does this:

function TBlockSocket.SockCheck(SockResult: Integer): Integer;
begin
   ResetLastError;
   if SockResult = integer(SOCKET_ERROR) then
   begin
     FLastError := synsock.WSAGetLastError;
     FLastErrorDesc := GetErrorDescEx;
   end;
   Result := FLastError;
end;


then in a connect it wraps the connect call in SockCheck:

procedure TBlockSocket.Connect(IP, Port: string);
var
   Sin: TVarSin;
begin
   SetSin(Sin, IP, Port);
   if FLastError = 0 then
   begin
     if FSocket = INVALID_SOCKET then
       InternalCreateSocket(Sin);
     SockCheck(synsock.Connect(FSocket, Sin));
     if FLastError = 0 then
       GetSins;
     FBuffer := '';
     FLastCR := False;
     FLastLF := False;
   end;
   ExceptCheck;
   DoStatus(HR_Connect, IP + ':' + Port);
end;


Changing

function TBlockSocket.SockCheck(SockResult: Integer): Integer;

to

function TBlockSocket.SockCheck(const SockResult: Integer): Integer;

does nothing.

Moreover, something really fishy is going on: look at the attached
project4 (now using synapse).
First I try outside a thread, and it correctly reports error 10060, then
inside a thread, where it reports 0, then again outside the thread (same
procedure) and this time it reports 0!

What's going on?

Bye
--
Luca


program project4;

{$mode objfpc}{$H+}

uses
  blcksock, Classes;

type
  { TInlineSocketThread }

  TNotifyError = procedure (m:string;n:integer) of object;

  TSocketThread = class(TThread)
  private
    FAddress:string;
    FPort:string;
    FErrMessage:string;
    FErrNum:integer;
    FUseSynchronize:boolean;
    FFinished:boolean;
    FOnError:TNotifyError;
    procedure SyncProcError;
    procedure ErrMsg(m:string;n:integer);
  public
    constructor Create(Address, Port:string; UseSynchronize:boolean);
    destructor Destroy;override;
    procedure Execute;override;
    property OnError:TNotifyError read FOnError write FOnError;
    property Finished:boolean read FFinished;
  end;

{ TSocketThread }

procedure TSocketThread.SyncProcError;
begin
  if Assigned(FOnError) then FOnError(FErrMessage,FErrNum);
end;

procedure TSocketThread.ErrMsg(m: string;n:integer);
begin
  if not Assigned(FOnError) then exit;
  FErrMessage:=m;
  FErrNum:=n;
  if FUseSynchronize then Synchronize(@SyncProcError) else SyncProcError;
end;


constructor TSocketThread.Create(Address,Port:string; UseSynchronize: boolean);
begin
  FAddress:=Address;
  FPort:=Port;
  FUseSynchronize:=UseSynchronize;
  inherited create(true); //create suspended
end;

destructor TSocketThread.Destroy;
begin
  terminate;
  while not FFinished do
      CheckSynchronize(100);
  inherited Destroy;
end;

procedure TSocketThread.Execute;
var s:TTCPBlockSocket;
    Connected:boolean;
  procedure PError(const msg:string);
  var e:integer;
  begin
    e:=s.LastError;
    if Connected then s.CloseSocket;
    Connected:=false;
    ErrMsg(msg,e);
  end;
begin
  Connected:=false;
  S:=TTCPBlockSocket.create;
  S.Connect(FAddress,FPort);
  if S.LastError=0 then
  begin
    connected:=true;
    ErrMsg('connected',0);
  end else
  begin
    Perror('connect');
  end;
  if Connected then
    S.CloseSocket;
  FFinished:=True;
end;

procedure SocketNoThread(FAddress,FPort:string);
var s:TTcpBlockSocket;
    Connected:boolean;
  procedure PError(msg:string);
  var e:integer;
  begin
    e:=s.LastError;
    if Connected then s.CloseSocket;
    Connected:=false;
    Writeln(msg,' ',e);
  end;
begin
  Connected:=false;
  S:=TTCPBlockSocket.create;
  S.Connect(FAddress,FPort);
  if S.LastError=0 then
  begin
    writeln('connected');
  end else
  begin
    PError('connect');
  end;
  if Connected then S.CloseSocket;
end;

{ TTest }
type
TTest=class
  FSocketThread:TsocketThread;
  procedure SockError(m:string;n:integer);
  constructor Create;
  destructor Destroy;override;
end;

{ TTest }

procedure TTest.SockError(m: string;n:integer);
begin
  writeln(m,' ',n);
end;

constructor TTest.Create;
begin
  FSocketThread:=TSocketThread.Create('1.2.3.4','1000',true);
  FSocketThread.OnError:=@SockError;
  FSocketThread.Resume;
  writeln('Thread started');
end;

destructor TTest.Destroy;
begin
  FSocketThread.Free;
  inherited Destroy;
end;


var Test:TTest;
begin
   Writeln('Each try should report "connect 10060"');
   Writeln('First try, no thread');
   SocketNoThread('1.2.3.4','1000');
   Writeln('Second try, in thread');
   Test:=TTest.Create;
   while not Test.FSocketThread.Finished do CheckSynchronize(100);
   Writeln('thread finished');
   Writeln('Third try, no thread');
   SocketNoThread('1.2.3.4','1000');
end.


_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Re: WSAGetLastError returns 0 when it shouldn't but I cannot see why

Lukas Gebauer
> Changing my "procedure PError(msg:string)" to "procedure PError(const
> msg:string)" in TSocketThread.Execute in project2 also fixes the
> problem. This smells like a bug somewhere in fpc/rtl, since I don't
> think it should make a difference. Anyway, this gives me no clue on
> how to "fix" synapse. Synapse does this:

It is IMHO bug in FPC, just because Synapse code working in
Delphi/Kylix threads perfectly. It have a problem on FPC threads
only, and as I see in this discussion, problem have other programs
too, not just Synapse. And I am pretty sure, Synapse working fine
with some older FPC versions.



--
Lukas Gebauer.

E-mail: [hidden email]
http://synapse.ararat.cz/ - Ararat Synapse - TCP/IP Lib.

_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Re: WSAGetLastError returns 0 when it shouldn't but I cannot see why

Luca Olivetti-2
El Thu, 06 Mar 2008 13:09:34 +0100
"Lukas Gebauer" <[hidden email]> escribió:


> It is IMHO bug in FPC, just because Synapse code working in
> Delphi/Kylix threads perfectly. It have a problem on FPC threads
> only, and as I see in this discussion, problem have other programs
> too, not just Synapse. And I am pretty sure, Synapse working fine
> with some older FPC versions.

And it also works fine with fpc under linux. That's why I wrote "fix"
in quotes, since I don't think that synapse is doing anything wrong.
Anyway, since I need/want to use synapse (actually I don't want to
write my own  ftp client, the one in synapse works just fine), while
the compiler gurus find the cause of the problem, I worked around it in
SockCheck by assigning a dummy code to FLastError if
synsock.WSAGetLastError returns 0.
I'm still worried of other side effects in windows TThread code.

Bye
--
Luca
_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

fix for GetLastError/WSAGetLastError with threads under windows [was WSAGetLastError returns 0 when it shouldn't but I cannot see why]

Luca Olivetti-2
En/na Luca Olivetti ha escrit:

> El Thu, 06 Mar 2008 13:09:34 +0100
> "Lukas Gebauer" <[hidden email]> escribió:
>
>
>> It is IMHO bug in FPC, just because Synapse code working in
>> Delphi/Kylix threads perfectly. It have a problem on FPC threads
>> only, and as I see in this discussion, problem have other programs
>> too, not just Synapse. And I am pretty sure, Synapse working fine
>> with some older FPC versions.
>
> And it also works fine with fpc under linux. That's why I wrote "fix"
> in quotes, since I don't think that synapse is doing anything wrong.
> Anyway, since I need/want to use synapse (actually I don't want to
> write my own  ftp client, the one in synapse works just fine), while
> the compiler gurus find the cause of the problem, I worked around it in
> SockCheck by assigning a dummy code to FLastError if
> synsock.WSAGetLastError returns 0.
> I'm still worried of other side effects in windows TThread code.

Jonas Maebe found the cause of the bug: when you use threads under
windows, there are calls to TlsGetValue (made in SysRelocateThreadVar)
to keep track of exception frames, and TlsGetValue reset LastError to 0.
If some windows developer is listening, please take a look at the patch
I posted on the bug report:

http://bugs.freepascal.org/view.php?id=10205

Bye
--
Luca

_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal