 |
BorlandTalk.com Borland discussion newsgroups
|
| View previous topic :: View next topic |
| Author |
Message |
PeterP Guest
|
Posted: Sun May 13, 2007 8:04 pm Post subject: Closing a TidTCPServer app remotely |
|
|
Hi, all-
Please excuse me if this question has been answered previously - there has
been a great deal of discussion about how to shut down TidTCPServer, but I
wasn't able to locate anything that related to my problem.
I'd like to be able to shut down an application which has an instance of
TidTCPServer in it, via a command from a client. That is, among all the
commands that any client can send to the server, one is "SHUTDOWN", and I
want that command to cause the server process to exit.
In the command handler for the "shutdown" command I tried the naive
procedure TForm1.ShutDownCmd(ASender: TIdCommand);
begin
server.active := false;
Form1.Release;
end;
which of course doesn't work, as many other people have discovered.
There can be multiple clients connected at the time this command arrives,
hence multiple threads.
Presumably I have to kill all the other threads and then tell the main
thread to exit - is that it? I'm new to thread programming, so some
guidance here would be greatly appreciated.
Thanks
Peter
--- posted by geoForum on http://delphi.newswhat.com |
|
| Back to top |
|
 |
Jamie Dale Guest
|
Posted: Sun May 13, 2007 8:11 pm Post subject: Re: Closing a TidTCPServer app remotely |
|
|
TIdTCPServer cannot be shut down from one of it's own threads. If you want
to shut it down then you would need to do it from the main program thread.
For that reason, I think the best method would be to send a message to the
main thread, so that it can de activate the server.
"PeterP" <aaa (AT) nowhere (DOT) ca> wrote in message
news:46471dbf$1 (AT) newsgroups (DOT) borland.com...
| Quote: | Hi, all-
Please excuse me if this question has been answered previously - there has
been a great deal of discussion about how to shut down TidTCPServer, but I
wasn't able to locate anything that related to my problem.
I'd like to be able to shut down an application which has an instance of
TidTCPServer in it, via a command from a client. That is, among all the
commands that any client can send to the server, one is "SHUTDOWN", and I
want that command to cause the server process to exit.
In the command handler for the "shutdown" command I tried the naive
procedure TForm1.ShutDownCmd(ASender: TIdCommand);
begin
server.active := false;
Form1.Release;
end;
which of course doesn't work, as many other people have discovered.
There can be multiple clients connected at the time this command arrives,
hence multiple threads.
Presumably I have to kill all the other threads and then tell the main
thread to exit - is that it? I'm new to thread programming, so some
guidance here would be greatly appreciated.
Thanks
Peter
--- posted by geoForum on http://delphi.newswhat.com |
|
|
| Back to top |
|
 |
Jamie Dale Guest
|
Posted: Sun May 13, 2007 8:13 pm Post subject: Re: Closing a TidTCPServer app remotely |
|
|
One other thought, you could use a message queue - Like a TLIST.
You could have the main program create another TThread which loops through
the TList continually and execute your custom commands. The TThread should
(I think) be able to close down the TIdTCPServer as long as it isn't one of
the servers own threads.
HTH
"PeterP" <aaa (AT) nowhere (DOT) ca> wrote in message
news:46471dbf$1 (AT) newsgroups (DOT) borland.com...
| Quote: | Hi, all-
Please excuse me if this question has been answered previously - there has
been a great deal of discussion about how to shut down TidTCPServer, but I
wasn't able to locate anything that related to my problem.
I'd like to be able to shut down an application which has an instance of
TidTCPServer in it, via a command from a client. That is, among all the
commands that any client can send to the server, one is "SHUTDOWN", and I
want that command to cause the server process to exit.
In the command handler for the "shutdown" command I tried the naive
procedure TForm1.ShutDownCmd(ASender: TIdCommand);
begin
server.active := false;
Form1.Release;
end;
which of course doesn't work, as many other people have discovered.
There can be multiple clients connected at the time this command arrives,
hence multiple threads.
Presumably I have to kill all the other threads and then tell the main
thread to exit - is that it? I'm new to thread programming, so some
guidance here would be greatly appreciated.
Thanks
Peter
--- posted by geoForum on http://delphi.newswhat.com |
|
|
| Back to top |
|
 |
Marais Guest
|
Posted: Mon May 14, 2007 5:37 pm Post subject: Re: Closing a TidTCPServer app remotely |
|
|
This looks like a good start. In the command handler I have
procedure TForm1.ShutDownCmd(ASender: TIdCommand);
var
MsgResult : LongBool;
begin
asender.thread.connection.Disconnect;
MsgResult := PostMessage(form1.Handle, CM_SHUTDOWN, 0, 0);
end;
and in the main thread's message handler, I have
procedure TForm1.CMShutdown(var Message: TMessage);
begin
memo1.Lines.add ('Shutdown received.');
server.active := false;
Form1.Release; {probably redundant}
application.Terminate;
inherited; {probably redundant}
end;
For testing, I establish three Telnet connections, and I send the shutdown
command from one of them. With the above code, at some point before the app
shuts down (at least in the IDE) I get two EIDClosedSocket exceptions.
Is there some way to traverse the active connections, shut them down
cleanly, and then terminate the application?
Peter
"Jamie Dale" <jamie.dale (AT) yahoo (DOT) com> wrote in message
news:46473117$1 (AT) newsgroups (DOT) borland.com...
| Quote: | One other thought, you could use a message queue - Like a TLIST.
You could have the main program create another TThread which loops through
the TList continually and execute your custom commands. The TThread should
(I think) be able to close down the TIdTCPServer as long as it isn't one
of the servers own threads.
HTH
"PeterP" <aaa (AT) nowhere (DOT) ca> wrote in message
news:46471dbf$1 (AT) newsgroups (DOT) borland.com...
Hi, all-
Please excuse me if this question has been answered previously - there
has
been a great deal of discussion about how to shut down TidTCPServer, but
I
wasn't able to locate anything that related to my problem.
I'd like to be able to shut down an application which has an instance of
TidTCPServer in it, via a command from a client. That is, among all the
commands that any client can send to the server, one is "SHUTDOWN", and I
want that command to cause the server process to exit.
In the command handler for the "shutdown" command I tried the naive
procedure TForm1.ShutDownCmd(ASender: TIdCommand);
begin
server.active := false;
Form1.Release;
end;
which of course doesn't work, as many other people have discovered.
There can be multiple clients connected at the time this command arrives,
hence multiple threads.
Presumably I have to kill all the other threads and then tell the main
thread to exit - is that it? I'm new to thread programming, so some
guidance here would be greatly appreciated.
Thanks
Peter
--- posted by geoForum on http://delphi.newswhat.com
|
|
|
| Back to top |
|
 |
Remy Lebeau (TeamB) Guest
|
Posted: Mon May 14, 2007 10:51 pm Post subject: Re: Closing a TidTCPServer app remotely |
|
|
"PeterP" <aaa (AT) nowhere (DOT) ca> wrote in message
news:46471dbf$1 (AT) newsgroups (DOT) borland.com...
| Quote: | In the command handler for the "shutdown" command I tried the naive
|
You can't do it that way. Setting the Active property inside a
command handler is a guaranteed deadlock. The Active property setter
closes all of the client sockets and then waits for all of the threads
to terminate. But the thread doing the shutdown is waiting for the
Active property setter to exit - a catch 22.
You need to post an asynchronous request to another thread (such as
the main thread) and let that thread handle the shutdown. You could
use PostMessage() to send a message to the MainForm window, and then
let its message handler do the shutdown. Or use the TIdNotify class
instead.
| Quote: | Presumably I have to kill all the other threads and then tell the
main thread to exit - is that it?
|
No.
Gambit |
|
| Back to top |
|
 |
Remy Lebeau (TeamB) Guest
|
Posted: Mon May 14, 2007 10:57 pm Post subject: Re: Closing a TidTCPServer app remotely |
|
|
"Marais" <marais (AT) x (DOT) y> wrote in message
news:SJY1i.13012$Xh3.7562@edtnps90...
| Quote: | MsgResult := PostMessage(form1.Handle, CM_SHUTDOWN, 0, 0);
|
You have to be careful using the Handle property in a worker thread
like that. It is not thread-safe, and can cause problems if the TForm
happens to recreate its HWND at the same time, such as during a
property change that requires the HWND to be refreshed.
It would be better to use PostThreadMessage() instead (there is a
global MainThreadID variable available), and then use the
TApplication.OnMessage event. Or use the TIdNotify class instead.
| Quote: | Form1.Release; {probably redundant}
|
Yes, that is redundant. There is no need for a form to free itself
like that, especially during a shutdown. Also, instead of calling
Application.Terminate(), you could just close the MainForm instead.
Which will trigger the OnCloseQuery and OnClose events, allowing the
MainForm to override the client's request to shut down the program if
it wants/needs to.
| Quote: | With the above code, at some point before the app shuts down
(at least in the IDE) I get two EIDClosedSocket exceptions.
|
That is perfectly normal. You can ignore those. When you set the
Active property to False, the active client sockets where closed, but
their threads were still running and the exceptions occured when the
threads tried to read the next command on each socket before detecting
the termination. Since you are inside the debugger, you see the
exceptions. You will not see them when the program is run outside the
debugger. And they ar raised in the context of the threads, so the
active connections will be shut down quitely and gracefully by
TIdTCPServer internally.
| Quote: | Is there some way to traverse the active connections, shut them
down cleanly, and then terminate the application?
|
You don't need to do that yourself. TIdTCPServer handles all of that
for you.
Gambit |
|
| Back to top |
|
 |
Marais Guest
|
Posted: Tue May 15, 2007 2:16 am Post subject: Re: Closing a TidTCPServer app remotely |
|
|
Remy-
Thanks for this. I wasn't aware that the window handle could change. I've
implemented your suggestions and all is now well. I have another question,
but that will be the subject of a separate posting.
Peter |
|
| Back to top |
|
 |
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
|