How to close TInetServer without except?

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

How to close TInetServer without except?

silvioprog
Hi,


destructor TTcpIpServerSocketThread.Destroy;
begin
  FSocket.StopAccepting;
  FSocket.Free;
  inherited Destroy;
end;

But, it returns:

"Could not accept a client connection on socket: 288, error 10004"

The erros occurs just when I run my project on IDE. I noticed that error is in this code:

Function TInetServer.Accept : Longint;

Var l : longint;

begin
  L:=SizeOf(FAddr);
  Result:=Sockets.fpAccept(Socket,@Faddr,@L);
  If Result<0 then
{$ifdef Unix}
    If SocketError=ESysEWOULDBLOCK then
      Raise ESocketError.Create(seAcceptWouldBlock,[socket])
    else
{$endif}
      Raise ESocketError.Create(seAcceptFailed,[Socket,SocketError]);
end;

The "Result" is returning -1, so, what I must do to it return 0? Overriding in a descendant class of TInetServer?

--
Silvio Clécio
My public projects - github.com/silvioprog

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

Re: How to close TInetServer without except?

zaher dirkey
​After termintate you need to wait the thread to stop, WaitFor here the function.

On Thu, May 2, 2013 at 8:57 PM, silvioprog <[hidden email]> wrote:
destructor TTcpIpServerSocketThread.Destroy;
begin
  FSocket.StopAccepting;
  FSocket.Free;
  inherited Destroy;
end;




--
I am using last revision of Lazarus, FPC 2.6 on Windows XP SP3

Best Regards
Zaher Dirkey

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

Re: How to close TInetServer without except?

silvioprog
2013/5/2 Zaher Dirkey <[hidden email]>
After termintate you need to wait the thread to stop, WaitFor here the function.

Yes, but in this case, WaitFor blocks my app.

--
Silvio Clécio
My public projects - github.com/silvioprog

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

Re: How to close TInetServer without except?

zaher dirkey

On Thu, May 2, 2013 at 10:45 PM, silvioprog <[hidden email]> wrote:

Yes, but in this case, WaitFor blocks my app.

​Yes, but before terminate your socket/client connections, you need also close the handle of it, or stop receive, it will return immateriality without receive (with error), so all connections will drop, and you wait to finish that.​



--
I am using last revision of Lazarus, FPC 2.6 on Windows XP SP3

Best Regards
Zaher Dirkey

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

Re: How to close TInetServer without except?

silvioprog
2013/5/2 Zaher Dirkey <[hidden email]>

On Thu, May 2, 2013 at 10:45 PM, silvioprog <[hidden email]> wrote:

Yes, but in this case, WaitFor blocks my app.

Yes, but before terminate your socket/client connections, you need also close the handle of it, or stop receive, it will return immateriality without receive (with error), so all connections will drop, and you wait to finish that.

--
I am using last revision of Lazarus, FPC 2.6 on Windows XP SP3

Best Regards
Zaher Dirkey

Yes. Please see full code here:


Lines 277 and 278. That is, I already do that. The problem now is how to stop the "Accept" but without errors.

I implemented the "Stop" method in socket, but I did not want to do it this ugly way.

--
Silvio Clécio
My public projects - github.com/silvioprog

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

Re: How to close TInetServer without except?

silvioprog
2013/5/2 silvioprog <[hidden email]>
2013/5/2 Zaher Dirkey <[hidden email]>

On Thu, May 2, 2013 at 10:45 PM, silvioprog <[hidden email]> wrote:

Yes, but in this case, WaitFor blocks my app.

Yes, but before terminate your socket/client connections, you need also close the handle of it, or stop receive, it will return immateriality without receive (with error), so all connections will drop, and you wait to finish that.

--
I am using last revision of Lazarus, FPC 2.6 on Windows XP SP3

Best Regards
Zaher Dirkey

Yes. Please see full code here:


Lines 277 and 278. That is, I already do that. The problem now is how to stop the "Accept" but without errors.

I implemented the "Stop" method in socket, but I did not want to do it this ugly way.

I tested current code on Linux, but unfortunately when I try to close, the app stays locked. :|

--
Silvio Clécio
My public projects - github.com/silvioprog

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

Re: How to close TInetServer without except?

zaher dirkey

On Thu, May 2, 2013 at 11:47 PM, silvioprog <[hidden email]> wrote:
I tested current code on Linux, but unfortunately when I try to close, the app stays locked. :|

​Yes headache :P​

​Do not close, i use Shutdown

function TmnSocket.DoShutdown(How: TmnShutdown): TmnError;
const
  cHow: array[TmnShutdown] of Integer = (0, SHUT_RD, SHUT_WR, SHUT_RDWR);
var
  c: Integer;
begin
  CheckActive;
  c := fpshutdown(FHandle, cHow[How]);
  if c = SOCKET_ERROR then
  begin
    Result := erFail;
//    RaiseLastOSError; do not raise an error, maybe it is disconnected by the other side
  end
  else
    Result := erNone;
end;



--
I am using last revision of Lazarus, FPC 2.6 on Windows XP SP3

Best Regards
Zaher Dirkey

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

Re: How to close TInetServer without except?

Ewald-2
In reply to this post by silvioprog

On 02 May 2013, at 22:00, silvioprog wrote:


Lines 277 and 278. That is, I already do that. The problem now is how to stop the "Accept" but without errors.

Using linux (or some other unix like thingie), you could cancel the thread using pthread_cancel(), the call will then return immediately with a specific (can't remember which) error code in errno (socketerror in this case I believe).

Problem with pthread_cancel is that there are quite a lot of cancelation points, see http://stackoverflow.com/questions/433989/posix-cancellation-points , so be careful with this approach.

Another way would be to use a non-blocking socket to accept connections... 

--
Ewald


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

Re: How to close TInetServer without except?

zaher dirkey

On Fri, May 3, 2013 at 12:51 AM, Ewald <[hidden email]> wrote:
pthread_cancel()

pthread_cancel()
​ ​
​ not clos
​e​
the handles i though​.​


--
I am using last revision of Lazarus, FPC 2.6 on Windows XP SP3

Best Regards
Zaher Dirkey

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

Re: How to close TInetServer without except?

silvioprog
In reply to this post by zaher dirkey
2013/5/2 Zaher Dirkey <[hidden email]>

On Thu, May 2, 2013 at 11:47 PM, silvioprog <[hidden email]> wrote:
I tested current code on Linux, but unfortunately when I try to close, the app stays locked. :|

Yes headache :P

Do not close, i use Shutdown

function TmnSocket.DoShutdown(How: TmnShutdown): TmnError;
const
  cHow: array[TmnShutdown] of Integer = (0, SHUT_RD, SHUT_WR, SHUT_RDWR);
var
  c: Integer;
begin
  CheckActive;
  c := fpshutdown(FHandle, cHow[How]);
  if c = SOCKET_ERROR then
  begin
    Result := erFail;
//    RaiseLastOSError; do not raise an error, maybe it is disconnected by the other side
  end
  else
    Result := erNone;
end;

--
I am using last revision of Lazarus, FPC 2.6 on Windows XP SP3

Best Regards
Zaher Dirkey

I tried with fpshotdown and closesocket, like this:


But, same error.

This is not the most serious problem. My dilemma now is to close the app. I hate working with threads. -.-'

--
Silvio Clécio
My public projects - github.com/silvioprog

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

Re: How to close TInetServer without except?

silvioprog
2013/5/2 silvioprog <[hidden email]>
I tried with fpshotdown ...

fpshutdown...

--
Silvio Clécio
My public projects - github.com/silvioprog

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

Re: How to close TInetServer without except?

Ludo Brands
In reply to this post by silvioprog
On 05/02/2013 10:00 PM, silvioprog wrote:
>
> Lines 277 and 278. That is, I already do that. The problem now is how to
> stop the "Accept" but without errors.
>
> I implemented the "Stop" method in socket, but I did not want to do it
> this ugly way.
>

Same solution as for recv and send. Or use blocking mode with a select
before accept, or use non blocking mode and deal with EAGAIN or
EWOULDBLOCK. Here you seem to use blocking mode and accept will only
return with a new connection or an error.

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

Re: How to close TInetServer without except?

Ewald-2
In reply to this post by zaher dirkey

On 03 May 2013, at 00:15, Zaher Dirkey wrote:


On Fri, May 3, 2013 at 12:51 AM, Ewald <[hidden email]> wrote:
pthread_cancel()

pthread_cancel()
​ ​
​ not clos
​e​
the handles i though​.​

That's true, but at least it returns control to you (= the programmer), so you can close the handles manually.

--
Ewald


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

Re: How to close TInetServer without except?

zaher dirkey

On Fri, May 3, 2013 at 12:18 PM, Ewald <[hidden email]> wrote:
That's true, but at least it returns control to you (= the programmer), so you can close the handles manually.

​I am notprefer force to close any thing, that will make more bugs in your application​, while it is work fine with other programmesr without using cancel it.

Best Regards
Zaher Dirkey

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

Re: How to close TInetServer without except?

silvioprog
In reply to this post by Ludo Brands
2013/5/3 Ludo Brands <[hidden email]>
On 05/02/2013 10:00 PM, silvioprog wrote:
>
> Lines 277 and 278. That is, I already do that. The problem now is how to
> stop the "Accept" but without errors.
>
> I implemented the "Stop" method in socket, but I did not want to do it
> this ugly way.
>

Same solution as for recv and send. Or use blocking mode with a select
before accept, or use non blocking mode and deal with EAGAIN or
EWOULDBLOCK. Here you seem to use blocking mode and accept will only
return with a new connection or an error.

Ludo

Could you give me an example in practice? Theoretically I understand, but I don't know do in practice. :/

Now, TTcpIpServer is working well. The new problem is: when I close the server with one or more clients connected, I got a memory leak.

--
Silvio Clécio
My public projects - github.com/silvioprog

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

Re: How to close TInetServer without except?

Ewald-2
In reply to this post by zaher dirkey

On 03 May 2013, at 11:30, Zaher Dirkey wrote:


On Fri, May 3, 2013 at 12:18 PM, Ewald <[hidden email]> wrote:
That's true, but at least it returns control to you (= the programmer), so you can close the handles manually.

​I am notprefer force to close any thing, that will make more bugs in your application​, while it is work fine with other programmesr without using cancel it.

Neither do I, but wasn't that what Silvio asked? [by saying: `The problem now is how to stop the "Accept" but without errors`]

I admit, killing an entire thread is a bit overkill for just getting back control from accept, but I also recall that he wanted to close the application [or am I seeing ghosts?]. But if you don't want to use pthread_cancel(), use non-blocking sockets -- In my experience though, it isn't worth the code if you just want to kill the application gracefully.

Anyway, I'm sure there are other ways to get this done (signals?), but these are two methods I know about. Each has it's bonuses and pitfalls.

--
Ewald


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

Re: How to close TInetServer without except?

zaher dirkey
In reply to this post by silvioprog

On Fri, May 3, 2013 at 6:57 PM, silvioprog <[hidden email]> wrote:
when I close the server with one or more clients connected, I got a memory leak.

​Check if the thread freed​?
​Try to stop server manually (by button or in Close event in the form)​

Best Regards
Zaher Dirkey

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

Re: How to close TInetServer without except?

zaher dirkey
In reply to this post by Ewald-2

On Fri, May 3, 2013 at 7:22 PM, Ewald <[hidden email]> wrote:
"Accept" but without errors

​You cant, Accept give you a handle of new socket or give you an error, not all is fatal error, just check what is it, if it a closed handle or shutdown.​

Best Regards
Zaher Dirkey

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

Re: How to close TInetServer without except?

silvioprog
In reply to this post by zaher dirkey
2013/5/3 Zaher Dirkey <[hidden email]>

On Fri, May 3, 2013 at 6:57 PM, silvioprog <[hidden email]> wrote:
when I close the server with one or more clients connected, I got a memory leak.

Check if the thread freed?
Try to stop server manually (by button or in Close event in the form)

Best Regards
Zaher Dirkey

Yes, I already do it.

Now I'm trying to terminate all unterminated clients:

destructor TTcpIpServerSocketThread.Destroy;
begin
  DoTerminateClients;
  FClients.Free;
  FSocket.Free;
  inherited Destroy;
end;

....

procedure TTcpIpServerSocketThread.DoTerminateClients;
var
  VClients: TList;
  VClient: Pointer;
  VThread: TTcpIpServerClientThread;
begin
  VClients := FClients.LockList;
  try
    for VClient in VClients do
    begin
      VThread := TTcpIpServerClientThread(VClient);
      if Assigned(VThread) and not VThread.Finished then
      begin
        VThread.FreeOnTerminate := False;
        VThread.Terminate;
        FreeAndNil(VThread.FClientSocket);
        VThread.WaitFor;
        FreeAndNil(VThread);
      end;
    end;
  finally
    FClients.UnlockList;
  end;
end;

I'm testing it, on Windows it worked fine, I'll test on Linux now...

--
Silvio Clécio
My public projects - github.com/silvioprog

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

Re: How to close TInetServer without except?

Ewald-2
In reply to this post by zaher dirkey
Once upon a time, Zaher Dirkey said:
> On Fri, May 3, 2013 at 7:22 PM, Ewald <[hidden email]> wrote:
>
>> "Accept" but without errors
>
> ​You cant, Accept give you a handle of new socket or give you an error, not
> all is fatal error, just check what is it, if it a closed handle or
> shutdown.​
Yes, I know that.

The point being that the answer to one of the OP sub-problems [the one
quoted _partially_ above], can be to either use:
- pthread_cancel() [overkill, I know, but nonetheless a solution]
- non-blocking sockets [not very code-efficient IMHO if you only want to
exit an application gracefully (high code versus ouput ratio)]
- something different (one can try experimenting with shutting down the
listening socket, using signals, ... but I haven't done so, so I can't
give any feedback on this)

--
Ewald

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