disable indy TIdTCPClient connect retries in firemonkey - firemonkey

i have this code to check connection to my server
so code is like this:
function CheckInternet(ssip:string): boolean;
begin
result:=false;
with form1.IdTCPClient1 do
try
ReadTimeout:=2000;
ConnectTimeout:=1000;
Port:=80;
Host:=ssip;
Connect;
Disconnect;
result:=true;
except
on E:EIdSocketError do
result:=false;
end;
end;
after running:
if server is online every thing is ok
but if server is online i got a lot of this error:
there is not difference in debug or release mode! both have error
also in android this cause two app crash and dont handling remain code!!..
how can i avoid this error?

What you see can happen only if you are calling CheckInternet() in a loop in the main UI thread and not catching raised exceptions. The popup messages are being displayed by a default exception handler within FMX when it catches an uncaught exception.
EIdSocketError is not the only type of exception that Connect() can raise. There are several other possible types, which you are not catching. You should remove the filter from your except block:
function CheckInternet(ssip:string): boolean;
begin
result:=false;
with form1.IdTCPClient1 do
try
ConnectTimeout:=1000;
Port:=80;
Host:=ssip;
Connect;
Disconnect;
result:=true;
except
result:=false;
end;
end;

Related

Cannot inspect variable inside Indy OnExecute event

using Indy with Delphi XE8 for a Tcp Server application I had necessity to inspect some local variables inside OnExecute event.
But setting a Breakpoint I do not understand why I get error "E2003 undeclared identifier"
trying to inspect or watch such local variables, as frame.
procedure TformMain.IdTCPServer1Execute(AContext: TIdContext);
var
frame, answer: string;
begin
...
frame := ReadLn(cETX, 50, 1024);
...
Thread.Queue(nil, procedure
begin
mmLog.Lines.Add(AContext.Binding.IP +'Bad Frame: '+ frame);
end
...
end;
Instead, in the thread queue I use to send info to the GUI, I can inspect correctly the Binding.IP, dispite to local strings...
Any idea if I am using the Delphi debugger in the right/wrong way ?

What is the purpose of RAISE_APPLICATION_ERROR?

I understand that RAISE_APPLICATION_ERROR associates a message error which only has a meaning to the user. But can't the user just write a similar exception the following way?
DECLARE
e_negative EXCEPTION;
BEGIN
IF v_sid < 0 THEN
RAISE e_negative;
...
EXCEPTION
WHEN e_negative THEN
DBMS_OUTPUT.PUT_LINE ('An id cannot be negative');
raise_application_error does more than print an error message to the console (like dbms_output.put_line does).
First, it's an actual error - it fails the statement, terminates the current block's execution, and propagates to outer blocks (similar to throw in Java or raise in Python).
Second, it actually returns this error regardless of the console. dbms_output's messages may be turned off or ignored, depending on the client. Raising an application error allows you to return the details of the failure, regardless of the client.

PL/SQL exception handling: do nothing (ignore exception)

This is a question I am asked very frequently. Since I couldn't find any exact duplicate on stackoverflow, I thought I'd post it as a reference.
Question:
In PL/SQL, I know how to catch exceptions and execute code when they are caught, and how to propagate them to the calling block.
For example, in the following procedure, the NO_DATA_FOUND exception is handled directly, while all other exceptions are raised to the calling block:
CREATE OR REPLACE PROCEDURE MY_PROCEDURE()
IS
BEGIN
do_stuff();
EXCEPTION
WHEN NO_DATA_FOUND THEN
-- Do something
handle_exception();
WHEN OTHERS THEN
-- Propagate exception
RAISE;
END;
But what command should I use to ignore one or all raised exceptions and return execution control back to the calling block?
While I agree that 99% of the time it is bad practice to silently ignore exceptions without at least logging them somewhere, there are specific situations where this is perfectly acceptable.
In these situations, NULL is your friend:
[...]
EXCEPTION
WHEN OTHERS THEN
NULL;
END;
Two typical situations where ignoring exceptions might be desirable are:
1) Your code contains a statement which you know will fail occasionally and you don't want this fact to interrupt your program flow.
In this case, you should enclose you statement in a nested block, as the following example shows:
CREATE OR REPLACE PROCEDURE MY_PROCEDURE()
IS
l_empoyee_name EMPLOYEES.EMPLOYEE_NAME%TYPE;
BEGIN
-- Catch potential NO_DATA_FOUND exception and continue
BEGIN
SELECT EMPLOYEE_NAME
INTO l_empoyee_name
FROM EMPLOYEES
WHERE EMPLOYEE_ID = 12345;
EXCEPTION
WHEN NO_DATA_FOUND THEN
NULL;
WHEN OTHERS THEN
RAISE;
END;
do_stuff();
EXCEPTION
WHEN OTHERS THEN
-- Propagate exception
RAISE;
END;
Note that PL/SQL generally does not allow for the On Error Resume Next type of exception handling known from Visual Basic, where all exceptions are ignored and the program continues to run as if nothing happened (see On error resume next type of error handling in PL/SQL oracle). You need to explicitly enclose potentially failing statements in a nested block.
2) Your procedure is so unimportant that ignoring all exceptions it throws will not affect your main program logic. (However, this is very rarely the case and can often result in a debugging nightmare in the long run)
BEGIN
do_stuff();
EXCEPTION
WHEN OTHERS THEN
-- Ignore all exceptions and return control to calling block
NULL;
END;
Another scenario when it does make sense to silently ignore exception:
When you call a script that is expected to create an object if it does not exist, and you do not have a create-or-replace syntax for that object.
PLSQL objects have a create-or-replace syntax, but tables and indexes do not.
Then we can put such scripts in a block and ignore the raised exception.

Indy's idSimpleServer reconnection

I'm want to be able to re-connect to a idSimpleServer after one client connects to it and then disconnects. The first client can connect and disconnect no problem but the next client can't. I did a simple test procedure to demonstrate it my problem.
procedure Tfrmmain.btnBlockingClick(Sender: TObject);
begin
Server1.BeginListen;
Server1.Listen;
CodeSite.Send(csmLevel2, 'Listen');
CodeSite.Send(csmLevel2, 'Server1.IOHandler.Connected', Server1.IOHandler.Connected);
try
while (Server1.Connected) do
begin
while Server1.IOHandler.CheckForDataOnSource() do
begin
CodeSite.Send(csmLevel3, 'InputBufferAsString', Server1.IOHandler.InputBufferAsString);
Server1.IOHandler.WriteLn('0006CANPDD');
end;
end;
finally
Server1.Disconnect;
CodeSite.Send(csmLevel4, 'Finally');
end;
end;
This give the following results in my codesite log:
Listen
Server1.IOHandler.Connected = True
Finally
Listen
Server1.IOHandler.Connected = False
Finally
Notice the second connection doesn't seem to bind the IOHandler properly. Not sure where I should be looking. Any ideas?
Thanks
Steve
The problem is that you are reusing the same TIdSimpleServer object each time.
After the first disconnect, the same IOHandler is reused for the next connection, but the IOHandler.ClosedGracefully property remains true from the earlier connection becaue it is not being reset each time. The ClosedGracefully property is reset only by the IOHander.Open() method, which TIdSimpleServer calls only when it creates a new IOHandler. Disconnect() does not free the IOHandler, but it does call IOHandler.Close().
The missing call to Open() on subsequent connections looks like a bug to me, so I have checked in a fix for it to Indy's SVN (rev 5103).
You can either upgrade to the latest SVN release, or else you will have to destroy the TIdSimpleServer.IOHandler (or the TIdSimpleServer itself) in between each connection.

how do I get windows SCM to restart my service when it fails

I have some windows services that i have written in delphi and they generally work very well, however on occasion i do get an exception thrown that can be considered fatal. When this happens the service is designed to stop.
My question is how do i exit the service in such a way that the SCM will automatically try to restart the service. (I have already set the recovery options for the service in the service manager)
MSDN states
A service is considered failed when it terminates without reporting a status of SERVICE_STOPPED to the service controller.
i have read this blog post Using the Automatic Recovery Features of Windows Services but i am not sure how to implement this in delphi.
i have allready tried the following
Setting the ErrCode Property of the TService to a non zero value.
Setting the stopped Parameter of the ServiceStop Event to false.
Raising an exception in the servicestop event handler.
EDIT 2013-08-06 added code example
Code Now Updated to show working example
Here is the code im using,
procedure TTestService.ServiceExecute(Sender: TService);
begin
while not (Terminated or FFatalError) do
begin
ServiceThread.ProcessRequests(False);
ReportStatus;
Sleep(100);
end;
if FFatalError then
Halt(1);
end;
FFatalError is a private boolean field on the TTestService class and is initialized to false on startup, it is only set to true if the worker thread (started in the TTestService.ServiceStart event) terminates with a fatal exception.
here is the OnTerminate event handler for the worker thread.
procedure TTestService.ThdTerm(Sender: Tobject);
var
E : Exception;
Thread : TThread;
begin
Thread := TThread(Sender);
if (Thread.FatalException <> nil) then
begin
E := Exception(Thread.FatalException);
GetExcCallStack(E);
EventLog.LogError(Thread.ClassName + ': ID:'+ IntToStr(Thread.ThreadID) +
' Stopped Unexpectedly!, '+ NEWLINE + E.ClassName +': ' + E.Message);
FFatalError := True;
end;
end;
The SCM will restart your service if it fails. But all the normal termination modes from a Delphi service do not count as failure. If you could raise an exception from the main service thread that was unhandled, then that would count as a failure.
However, I think the simplest way for you to force a process termination that is treated as a failure is to call ExitProcess. You could equally well call the Delphi RTL function Halt which will ultimately call ExitProcess. However, since your process is probably in a bad state I'd be inclined to go straight to ExitProcess.
As has already been commented, avoiding the exception in the first place would be the ideal solution.

Resources