Sign in Join

Live chat for Free Pascal, Lazarus, Delphi and every Pascal programmer.

Mailing lists / fpc-pascal / 2008-02

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

11 messages · 3 people · –

Reply by email Subscribe to this list Your subscription

Read-only archive. Use j and k to move between messages.

L
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).

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 ;-)

Reply by email

Luca Olivetti
to L
Show quoted text 16 lines
> 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

Reply by email

L
to L: even if it couldn't I am also working on this issue still. I had the WSAGetLastError…
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;

Reply by email

L
to L
Show quoted text 13 lines
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.

Reply by email

L
to L
Show quoted text 9 lines
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.

Reply by email

Luca Olivetti
to L: Aha.. I changed the by Value parameter to a CONST parameter in the error procedure…

En/na L ha escrit:

Show quoted text 10 lines
> 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

Reply by email

L
to L: http://bugs.freepascal.org/view.php?id=10205 Attached program with problem. This may be…
This seriously worries me, since I use threads extensively, and I

mostly use call by value

Show quoted text 6 lines
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 ;-)

Reply by email

Luca Olivetti
to Luca Olivetti: En/na L ha escrit: This seriously worries me, since I use threads extensively, and I…

En/na Luca Olivetti ha escrit:

Show quoted text 15 lines
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

Reply by email

Lukas Gebauer
to Luca Olivetti
Show quoted text 5 lines
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: http://synapse.ararat.cz/ - Ararat Synapse - TCP/IP Lib.

Reply by email

Luca Olivetti
to Lukas Gebauer
Show quoted text 5 lines
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

Reply by email

Luca Olivetti
to Luca Olivetti

En/na Luca Olivetti ha escrit:

Show quoted text 18 lines
El Thu, 06 Mar 2008 13:09:34 +0100 "Lukas Gebauer" 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

Reply by email