-
-
Notifications
You must be signed in to change notification settings - Fork 262
Fix CORE-5173 #9
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -558,6 +558,31 @@ const StmtNode* BlockNode::execute(thread_db* tdbb, jrd_req* request, ExeState* | |
|
||
if (handlers && handlers->statements.getCount() > 0) | ||
{ | ||
// First of all rollback failed work | ||
if (transaction != sysTransaction) | ||
{ | ||
count = *request->getImpure<SLONG>(impureOffset); | ||
|
||
// Since there occurred an error (req_unwind), undo all savepoints | ||
// up to, _but not including_, the savepoint of this block. | ||
// That's why transaction->rollbackToSavepoint() cannot be used here | ||
// The savepoint of this block will be dealt with below. | ||
// Do this only if error handlers exist. If not - leave rollbacking to caller node | ||
while (transaction->tra_save_point && | ||
transaction->tra_save_point->sav_next && | ||
count < transaction->tra_save_point->sav_next->sav_number) | ||
{ | ||
transaction->rollforwardSavepoint(tdbb); | ||
} | ||
// There can be no savepoints above the given one | ||
if (transaction->tra_save_point && transaction->tra_save_point->sav_number > count) | ||
{ | ||
transaction->rollbackSavepoint(tdbb); | ||
} | ||
// after that we still have to have our savepoint. If not - CORE-4424/4483 is sneaking around | ||
fb_assert(transaction->tra_save_point && transaction->tra_save_point->sav_number == count); | ||
} | ||
|
||
temp = parentStmt; | ||
bool handled = false; | ||
const NestConst<StmtNode>* ptr = handlers->statements.begin(); | ||
|
@@ -575,31 +600,6 @@ const StmtNode* BlockNode::execute(thread_db* tdbb, jrd_req* request, ExeState* | |
temp = handlerNode->action; | ||
exeState->errorPending = false; | ||
|
||
if (transaction != sysTransaction) | ||
{ | ||
count = *request->getImpure<SLONG>(impureOffset); | ||
|
||
// Since there occurred an error (req_unwind), undo all savepoints | ||
// up to, _but not including_, the savepoint of this block. | ||
// That's why transaction->rollbackToSavepoint() cannot be used here | ||
// The savepoint of this block will be dealt with below. | ||
// Do this only if error handlers exist. If not - leave rollbacking to caller node | ||
|
||
while (transaction->tra_save_point && | ||
transaction->tra_save_point->sav_next && | ||
count < transaction->tra_save_point->sav_next->sav_number) | ||
{ | ||
transaction->rollforwardSavepoint(tdbb); | ||
} | ||
// There can be no savepoints above the given one | ||
if (transaction->tra_save_point && transaction->tra_save_point->sav_number > count) | ||
{ | ||
transaction->rollbackSavepoint(tdbb); | ||
} | ||
// after that we still have to have our savepoint. If not - CORE-4424/4483 is sneaking around | ||
fb_assert(transaction->tra_save_point && transaction->tra_save_point->sav_number == count); | ||
} | ||
|
||
// On entering looper exeState->oldRequest etc. are saved. | ||
// On recursive calling we will loose the actual old | ||
// request for that invocation of looper. Avoid this. | ||
|
@@ -647,9 +647,16 @@ const StmtNode* BlockNode::execute(thread_db* tdbb, jrd_req* request, ExeState* | |
|
||
if (handled && transaction != sysTransaction) | ||
{ | ||
// Check that exception handlers wee executed in context of right savepoint. | ||
// Check that exception handlers were executed in context of right savepoint. | ||
// If not - mirror copy of CORE-4424 or CORE-4483 is around here. | ||
fb_assert(transaction->tra_save_point && transaction->tra_save_point->sav_number == count); | ||
// Except the case of nested exception handlers and throwing in inner one. | ||
// In this case execution flow is like this: | ||
// inner before (block that rollbacking savepoints above) | ||
// outer before | ||
// outer after (this block) | ||
// inner after | ||
// Because of this following assert is commentd out | ||
//fb_assert(transaction->tra_save_point && transaction->tra_save_point->sav_number == count); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What is "before" and "after" here? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. These are parts of code managing savepoints that are placed before and after call of looper for exception handlers, as written in parentheses. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'd prefer to see the bad execution flow fixed rather than working around with a disabled assert. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm not sure that recursive exceptions handling is a bad thing. It can be "as designed". In any case this is a bigger work for different ticket. |
||
for (const Savepoint* save_point = transaction->tra_save_point; | ||
save_point && count <= save_point->sav_number; | ||
save_point = transaction->tra_save_point) | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In tra.cpp, one condition is ">" and another one is ">=". Is it correct that both conditions in this patch are strict inequalities?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes. In tra.cpp rolling forward must stop immediatelly before given savepoint, here - before one savepoint before the given one because there we must rollback the savepoint, here - rollback everything but the savepoint as it must be applied afterward.