I have a loop which executes a proc.
That proc can throw RAISERROR which, of course, stops the loop and the whole program.
Is there any way to ignore that error and continue the loop?
In normal languages I can CATCH the error, but what is possible in Sybase T-SQL?
I found EXCEPTION section (similar to Oracle) and CONTINUE_AFTER_RAISERROR, but they are in Sybase IQ, not in ASE.
Any idea?
Related
I want to get more information about possible exceptions raised in the child. I know it could be done by looking at stderr like below:
try:
completed_process = subprocess.run(['python3', 'test.py'], capture_output=True, check=True)
except subprocess.CalledProcessError as e:
print(e.stderr)
However, I wonder if I could directly get the exception raised in the child such as ModuleNotFoundError?
Alternative: some tool for parsing the raw stderr.
This isn't possible, because the process tools used in forking / joining aren't aware of any detail except return code and maybe the OS signal that caused the exit.
If you want in-process detail like exceptions you're actually looking for threading.
Threading is a way of having parallelism for a subroutine in the same logical processes, and which would allow you to capture in-process details like exceptions.
For python3, details are here: https://docs.python.org/3/library/threading.html
Is it safe to call Exit on try except?
Or should I call raise instead?
I tried both example below and at raise example, the trace went through Delphi's internal library code. While exit just exit the procedure and nothing more.
I read that it's better to preserve application stack or queue or something like that. Will calling exit will break that stack?
Example 1 (raise)
SDDatabase1.StartTransaction;
Try
SDQuery1.ApplyUpdates;
SDDatabase1.Commit;
SDQuery1.CommitUpdates;
Except
SDDatabase1.Rollback;
SDQuery1.RollbackUpdates;
raise;
End;
..............//other codes I don't want to execute
Example 2 (exit)
SDDatabase1.StartTransaction;
Try
SDQuery1.ApplyUpdates;
SDDatabase1.Commit;
SDQuery1.CommitUpdates;
Except
SDDatabase1.Rollback;
SDQuery1.RollbackUpdates;
MessageDlg('Save Failed because: '+E.Message, mtError, [mbOK], 0);
exit;
end;
..............//other codes I don't want to execute
It's rare that alternate options (A vs. B) can be objectively evaluated as one is "always better" than the other. This is why it's important to properly understand the differences and implications of each.
When examined in isolation of a single method both your examples skip the code after the end of the except block. However, one leaves in an exception-state and the other doesn't. This has implications not in the method you write, but in the callers (direct and indirect) of your method.
procedur Caller1;
begin
//...[A]
Caller2;
//...[B]
end;
procedure Caller2;
begin
//...[C]
CallDatabaseMethod; {Will raise; or Exit; based on example chosen}
//...[D]
end;
The key distinction between your 2 examples is:
Example 1 is able to report the failure state up the call-stack.
Example 2 hides this information because the exception handler swallows the exception.
Example 1 would also skip [B] and [D] code. However, Example 2 would execute [B] and [D] code. When you understand this difference, you are then empowered to decide whether [B] and [D] should be executed.
However, I suspect that more often than not, the fact that CallDatabaseMethod failed to do everything correctly suggests that [B] and [D] should not be called. E.g. Suppose the database method updates customer account data and [B] and [D] perform action related to sending the latest statement. You probably don't want to send a statement when the update failed!
That said, if your method can be considered as "successfully completed" in spite of the exception, then by all means swallowing the exception is perfectly acceptable. E.g. Suppose you have a method to "Add a Row" and its post condition is simply that the row must exist in the database. Then if your database return a PK violation, obviously the row does exist. In this case it makes perfect sense to swallow the exception.
You can of course tweak the implementation of example 2 so as to not hide the error.
If your method is written as a function that returns success or failure state as a result, then callers can use this to resolve the aforementioned problems. E.g.
function Caller1: Boolean;
begin
Result := Caller2;
{Caller can decide to skip/ignore/do something different}
if Result then ...
end;
function Caller2: Boolean;
begin
Result := CallDatabaseMethod;
{Caller can decide to skip/ignore/do something different}
if Result then ...
end;
function CallDatabaseMethod: Boolean;
begin
Result := True;
//...
try
//...
except
on E: ExceptionType do
begin
//...
Result := False;
end;
end;
//...
end;
This is the same way the Windows API works. It does have its pros and cons:
Use return codes means caller has to remember to check for errors. (A common source of WinAPI questions on this site involve programmers failing to check for error return by API functions.)
So it's clearly an advantage that the exception model cannot be "ignored" by callers - they will surface eventually, even if it involves crashing the application.
But conversely again there's the disadvantage that the code to ignore exceptions that have been forced upon you is messier.
It's also important to caution against getting into a situation where large amounts of code run inside except blocks1.
The other disadvantage of structure exception handling is that it does have a significant performance overhead, so ideally you don't want to raise and handle them too often.
I recommend that the best approach is to determine which kinds of errors can be considered "normal" and ensure this is processed using explicit error results rather than exceptions. Certainly instances of 1 above are prime candidates.
Finally David has already flagged concerns with your message dialog in example 2. So this comment is on the assumption that this code always runs in a user context.
I understand the urge to show the message immediately. You have context that is lost by the time the exception propagates to the application level handler. One option to consider is using Abort which simply raises an EAbort exception.
try
//...
except
on E: ExceptionType do
begin
MessageDlg(...);
Abort;
end;
end;
The default application exception should ignore this exception and not display a message. If you have your own handler, you should similarly check the exception class before displaying any message.
As a side note I'd like to consider a particular sentence in the question.
I read that it's better to preserve application stack or queue or something like that.
Obviously if you're not sure about what you read, it's difficult explain it to you. You might already have a clearer picture based on earlier parts of my answer.
However, it might be referring to a different problem with another approach to exception handling. Raising a new exception. (You avoid this problem with raise; because it re-raises the original exception in original context.) This is the sort of thing is done to provide "more meaningful error message - similar to your example 2.
try
except
raise EOtherError.Create('My Message');
end;
The problem with the above is that when this exception eventually propagates to the application handler you've lost the original class; original exception address; and the original message. This approach often results in a clearer error to the user: e.g. "Unable to open file filename" but hides information that might have been useful in troubleshooting. E.g. Was it a disk error, was file not file, was it access permission error.
So: an important thing to think about whenever handling errors (no matter what approach you use) is: will there be enough information to resolve an error should it occur?
Both are safe in principle, but it's impossible to recommend one or other approaches. It depends on your design intentions. You have to decide which is appropriate given the intended usage of the code.
If you handle the exception in this code, and leave the function with exit, then the execution returns to the calling function, and it has no inkling of whether or not the function succeeded or failed. This may be problematic.
If you re-raise the exception, execution will move to the next suitable exception handler up the call stack, passing through any finally blocks along the way.
So, behaviour will differ, and it's down to you to decide which you want.
It is a common beginner's mistake to attempt to handle exceptions further down the call stack than is ideal. For example, suppose you want your code to be used in both a GUI app and a non-visual app. Your use of MessageDlg would not be appropriate in a non-visual app.
In a GUI app it is common for most actions to be in response to user input, for instance a button press. Exceptions typically should result in the entire operation being aborted. In which case you should not attempt to handle exceptions at all. Let them pass to the application level exception handler.
Finally, your code treats all exceptions in the same way. This is often ill-advised. For instance, an access violation should surely be treated differently from a database error.
I hope this question isn't too broad.
I'm working with a legacy Ada application. This application is built around a very old piece of middleware that handles, among other things, our IPC. For the sake of this question, I can boil the middleware's provisions down to
1: a message loop that processes messages (from other programs or this program)
2: a function to send messages to this program or others
3: a function to read from a database
The program operates mainly on a message loop - simply something like
loop
This_Msg := Message_Loop.Wait_For_Message; -- Blocking wait call
-- Do things based on This_Msg's ID
end loop
however there are also callbacks that can be triggered by external stimuli. These callbacks run in their own threads. Some of these callbacks call the database-reading function, which has always been fine, EXCEPT, as we recently discovered, in a relatively rare condition. When this condition occurs, it turns out it isn't safe to read from the database when the message loop is executing its blocking Wait_For_Message.
It seemed like a simple solution would be to use a protected object to synchronize the Wait_For_Message and database read: if we try to read the database while Wait_For_Message is blocking, the read will block until Wait_For_Message returns, at which point the Wait_For_Message call will be blocked until the database read is complete. The next problem is that I can't guarantee the message loop will receive a message in a timely fashion, meaning that the database read could be blocked for an arbitrary amount of time. It seems like the solution to this is also simple: send a do-nothing message to the loop before blocking, ensuring that the Wait_For_Message call will yield.
What I'm trying to wrap my head around is:
If I send the do-nothing message and THEN block before the database read, I don't think I can guarantee that Wait_For_Message won't have returned, yielded, processed the do-nothing message, and started blocking again before the pre-database read block. I think I conceptually need to start blocking and THEN push a message, but I'm not sure how to do this. I think I could handle it with a second layer of locks, but I can't think of the most efficient way to do so, and don't know if that's even the right solution. This is really my first foray into concurrency in Ada, so I'm hoping for a pointer in the right direction.
Perhaps you should use a task for this; the following would have the task waiting at the SELECT to either process a message or access the DB while another call on an entry during the processing would queue on that entry for the loop to reiterate the select, thus eliminating the problem altogether... unless, somehow, your DB-access calls the message entry; but that shouldn't happen.
Package Example is
Task Message_Processor is
Entry Message( Text : String );
Entry Read_DB( Data : DB_Rec );
End Message_Processor;
End Example;
Package Body Example is
Task Body Message_Processor is
Package Message_Holder is new Ada.Containers.Indefinite_Holders
(Element_Type => String);
Package DB_Rec_Holder is new Ada.Containers.Indefinite_Holders
(Element_Type => DB_Rec);
Current_Message : Message_Holder.Holder;
Current_DB_Rec : DB_Rec_Holder.Holder;
Begin
MESSAGE_LOOP:
loop
select
accept Message (Text : in String) do
Current_Message:= Message_Holder.To_Holder( Text );
end Message;
-- Process the message **outside** the rendevouz.
delay 1.0; -- simulate processing.
Ada.Text_IO.Put_Line( Current_Message.Element );
or
accept Read_DB (Data : in DB_Rec) do
Current_DB_Rec:= DB_Rec_Holder.To_Holder( Data );
end Message;
-- Process the DB-record here, **outside** the rendevouz.
or
Terminate;
end select;
end loop MESSAGE_LOOP;
End Message_Processor;
End Example;
I'm currently trying to wrap my mind around the correct way to use exceptions in Haskell. How exceptions work is straight-forward enough; I'm trying to get a clear picture of the correct way to interpret them.
The basic position is that, in a well-designed application, exceptions shouldn't escape to the top-level. Any exception that does is clearly one which the designer did not anticipate - i.e., a program bug (e.g., divide by zero), rather than an unusual run-time occurrence (e.g., file not found).
To that end, I wrote a simple top-level exception handler that catches all exceptions and prints a message to stderr saying "this is a bug" (before rethrowing the exception to terminate the program).
However, suppose the user presses Ctrl+C. This causes an exception to be thrown. Clearly this is not any kind of program bug. However, failing to anticipate and react to a user abort such as this could be considered a bug. So perhaps the program should catch this and handle it appropriately, doing any necessary cleanup before exiting.
The thing is, though... The code that handles this is going to catch the exception, release any resources or whatever, and then rethrow the exception! So if the exception makes it to the top-level, that doesn't necessarily mean it was unhandled. It just means we wanted to exit quickly.
So, my question: Should exceptions be used for flow-control in this manner? Should every function that explicitly catches UserInterrupt use explicit flow-control constructs to exit manually rather than rethrow the exception? (But then how does the caller know to also exit?) Is it OK for UserInterrupt to reach the top-level? But in that case, is it OK for ThreadKilled too, by the same argument?
In short, should the interrupt handler make a special case for UserInterrupt (and possibly ThreadKilled)? What about a HeapOverflow or StackOverflow? Is that a bug? Or is that "circumstance beyond the program's control"?
Cleaning up in the presence of exceptions
However, failing to anticipate and react to a user abort such as this could be considered a bug. So perhaps the program should catch this and handle it appropriately, doing any necessary cleanup before exiting.
In some sense you are right — the programmer should anticipate exceptions. But not by catching them. Instead, you should use exception-safe functions, such as bracket.
For example:
import Control.Exception
data Resource
acquireResource :: IO Resource
releaseResource :: Resource -> IO ()
workWithResource = bracket acquireResource releaseResource $ \resource -> ...
This way the resources will be cleaned up regardless of whether the program will be aborted by Ctrl+C.
Should exceptions reach top level?
Now, I'd like to address another statement of yours:
The basic position is that, in a well-designed application, exceptions shouldn't escape to the top-level.
I would argue that, in a well-designed application, exceptions are a perfectly fine way to abort. If there are any problems with this, then you're doing something wrong (e.g. want to execute a cleanup action at the end of main — but that should be done in bracket!).
Here's what I often do in my programs:
Define a data type that represents any possible error — anything that might go wrong. Some of them often wrap other exceptions.
data ProgramError
= InputFileNotFound FilePath IOException
| ParseError FilePath String
| ...
Define how to print errors in a user-friendly way:
instance Show ProgramError where
show (InputFileNotFound path e) = printf "File '%s' could not be read: %s" path (show e)
...
Declare the type as an exception:
instance Exception ProgramError
Throw these exceptions in the program whenever I feel like it.
Should I catch exceptions?
Exceptions that you anticipate must be caught and wrapped (e.g. in InputFileNotFound) to give them more context. What about the exceptions that you don't anticipate?
I can see some value in printing "it's a bug" to the users, so that they report the problem back to you. If you do this, you should anticipate UserInterrupt — it's not a bug, as you say. How you should treat ThreadKilled depends on your application — literally, whether you anticipate it!
This, however, is orthogonal to the "good design" and depends more on what kind of users you're targeting, what you expect of them and what they expect of your program.
The response may range from just printing the exception to a dialog that says "we're very sorry, would you like to submit a report to the developers?".
Should exceptions be used for flow-control in this manner?
Yes. I highly recommend you read Breaking from a loop, which shows how Either and EitherT at their core at nothing more than abstractions for exiting from a code block early. Exceptions are just a special case of this behavior where you exit because of an error, but there is no reason why that should be the only case in which you exit prematurely.
I have never worked with threads before, and now I'm trying to create a thread with a query to check database status. The query is as follows:
select (*) as DBCount from v$datafile where status in 'OFFLINE';.
This query returns the total number of all the databases that are offline. Now I want to create a thread in Delphi that will execute this query in the background of my application when I run it and display the results on a label.
Multithreading is hard. You may be better off using a simple threading framework like AsyncCalls.
Following StackOverlow threads may give you more information on how to solve your problem:
Delphi - Threading frameworks
How Do I Choose Between the Various Ways to do Threading in Delphi?
Delphi thread that waits for data, processes it, then resumes waiting
This is fairly easy to do using AsyncCalls. Let's assume your non-threaded code looks like this (ignoring all error handling):
Query := 'select (*) as DBCount from...';
ExecuteSQL(SqlConnection,Query);
SqlResult := GetSqlResult(SqlConnection);
SqlRow := GetSqlRow(SqlResult);
MyLabel.Text := SqlRow[0];
...Go on to do other things...
Where the second line is blocking (waiting for the server to reply). Your new code would look like this:
uses AsyncCalls; //added to your existing uses statement
...
procedure DoesSomething();
var Thread: TAsyncCall; //your interface to AsyncCalls
procedure AsyncSqlCall(); //this is a LOCAL procedure
Query := 'select (*) as DBCount from...';
ExecuteSQL(SqlConnection,Query);
SqlResult := GetSqlResult(SqlConnection);
SqlRow := GetSqlRow(SqlResult);
EnterMainThread;
try
Assert(GetCurrentThreadId = MainThreadId);
MyLabel.Text := SqlRow[0];
finally
LeaveMainThread;
end;
begin //this begins proc DoSomething()
...
Thread := LocalAsyncCall(#AsyncSqlCall);
...Go on to do other things...
end;
All we've done is put the blocking SQL calls in a local proc and told AsyncCalls to execute it in another thread, while the main thread continues executing. The only tricky part was using the VCL, which is not thread-safe. So I had that line safely run in the main thread.
If at some point you need to be sure the Async thread has completed, you would execute this line to block the main thread till AsyncSqlCall terminates:
Thread.sync;
The really nice thing here is that AsyncCalls handles all the stuff about creating a thread pool, creating threads, etc. Though not shown in this example, you can pass variables to your thread, and return a value. You don't have to use a local proc, but doing so gives it access to all local vars. You could make all this global, and then launch the Async thread in one routine, and test for its completion in another.
Restrictions:
Your Async thread must not touch (read or write) anything but its own variables, and your main thread must not touch them while the Async thread is running. YOU must code it that way. Nothing will stop you from creating total chaos. In the above example, your main thread must not touch Query, SqlConnection, SqlResult, and SqlRow. If any part of your code used one of those vars before the Thread.sync call, your code would work -- but throw exceptions in weird places you never expected. So keep it simple.
Your Async thread must not use the VCL. The sample above shows one of several ways to safely get around this limitation.
Finally:
AsyncCalls is not a full Multi-Threading framework. It's just a way of calling procs & functions asynchronously (i.e. without waiting). Don't try to push it too far -- by which I mean, don't try to make it the basis of a fully multitasking program.
In Delphi there is TThread class. You can create such thread using simple wizard from Delphi IDE (in Turbo Delphi: File->New->Delphi Projects->Delphi Files->Thread Obcjet). In its constructor create connection to database, and in Execute method you can create loop that query database, update some global variable (NOT declared as threadvar) and sleep some time.
Here you can find a discussion about using threads on DataBase.
Simple Thread Sample Delphi
There are some code that can be usefull for you.
Regards.