Skip to content
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

AV at engine when some statement under autonomous transaction dropped transaction level savepoint [CORE2558] #2968

Closed
firebird-automations opened this issue Jul 16, 2009 · 12 comments

Comments

@firebird-automations
Copy link
Collaborator

Submitted by: @hvlad

Attachments:
cto.zip

Commits: 4d1e602 7964c35

====== Test Details ======

"Could not find the specified attachment on the server"

@firebird-automations
Copy link
Collaborator Author

Commented by: @hvlad

Extract database backup, restore it and run query :

execute procedure test_trans;

@firebird-automations
Copy link
Collaborator Author

Modified by: @hvlad

Attachment: cto.zip [ 11475 ]

@firebird-automations
Copy link
Collaborator Author

Commented by: @hvlad

It seems autonomous transaction must start its own savepoint right after transaction start. In user application it is started by EXE_start when request begins its execution. But in autonomous transaction case request is already executing.

Proposed patch is :

cvs -z9 diff -u -wb -- dsql\StmtNodes.cpp (in directory C:\FB2\fb25.trace\src\)
Index: dsql/StmtNodes.cpp

RCS file: /cvsroot/firebird/firebird2/src/dsql/StmtNodes.cpp,v
retrieving revision 1.7
diff -u -w -b -r1.7 StmtNodes.cpp
--- dsql/StmtNodes.cpp 8 Jan 2009 09:26:05 -0000 1.7
+++ dsql/StmtNodes.cpp 16 Jul 2009 06:58:05 -0000
@@ -29,6 +29,7 @@
#⁠include "../jrd/exe_proto.h"
#⁠include "../jrd/par_proto.h"
#⁠include "../jrd/tra_proto.h"
+#⁠include "../jrd/vio_proto.h"
#⁠include "../dsql/gen_proto.h"
#⁠include "../dsql/pass1_proto.h"

@@ -139,6 +140,8 @@
request->req_transaction);
tdbb->setTransaction(request->req_transaction);

+ VIO_start_save_point(tdbb, request->req_transaction);
+
if (!(tdbb->getAttachment()->att_flags & ATT_no_db_triggers))
{
// run ON TRANSACTION START triggers
@@ -148,6 +151,8 @@
return action;
}

+ const jrd_tra* transaction = request->req_transaction;
+
switch (request->req_operation)
{
case jrd_req::req_return:
@@ -157,6 +162,14 @@
EXE_execute_db_triggers(tdbb, request->req_transaction, jrd_req::req_trigger_trans_commit);
}

+ if ((transaction && (transaction != tdbb->getDatabase()->dbb_sys_trans) &&
+ transaction->tra_save_point &&
+ !(transaction->tra_save_point->sav_flags & SAV_user) &&
+ !transaction->tra_save_point->sav_verb_count))
+ {
+ VIO_verb_cleanup(tdbb, request->req_transaction);
+ }
+
{ // scope
Firebird::AutoSetRestore2<jrd_req*, thread_db> autoNullifyRequest(
tdbb, &thread_db::getRequest, &thread_db::setRequest, NULL);
@@ -176,6 +189,14 @@
jrd_req::req_trigger_trans_commit);
}

+ if ((transaction && (transaction != tdbb->getDatabase()->dbb_sys_trans) &&
+ transaction->tra_save_point &&
+ !(transaction->tra_save_point->sav_flags & SAV_user) &&
+ !transaction->tra_save_point->sav_verb_count))
+ {
+ VIO_verb_cleanup(tdbb, request->req_transaction);
+ }
+
Firebird::AutoSetRestore2<jrd_req*, thread_db> autoNullifyRequest(
tdbb, &thread_db::getRequest, &thread_db::setRequest, NULL);
TRA_commit(tdbb, request->req_transaction, false);

@firebird-automations
Copy link
Collaborator Author

Commented by: @asfernandes

Vlad, I had doubts if that is a fix for the root of the problem.

1) Many places verify !NULL tra_save_point, so it seams as a valid case
2) It should not be necessary to have an extra savepoint in autonomous transaction. There is already the transaction savepoint
3) I do not understand when this code in exe.cpp would execute:
if (transaction != tdbb->getDatabase()->dbb_sys_trans) {
for (const Savepoint* save_point = transaction->tra_save_point;
save_point && save_point_number < save_point->sav_number;
save_point = transaction->tra_save_point)
{
VIO_verb_cleanup(tdbb, transaction);
}
}

But if it executes, looks like VIO_verb_cleanup could leave a NULL tra_save_point outside of an autonomous transaction.

Therefore, I suggest these changes:

Index: src/jrd/exe.cpp

RCS file: /cvsroot/firebird/firebird2/src/jrd/exe.cpp,v
retrieving revision 1.304
diff -u -p -r1.304 exe.cpp
--- src/jrd/exe.cpp 13 Jul 2009 10:00:41 -0000 1.304
+++ src/jrd/exe.cpp 17 Jul 2009 01:35:48 -0000
@@ -1311,7 +1311,7 @@ static jrd_nod* erase(thread_db* tdbb, j
rpb->rpb_stream_flags &= ~RPB_s_refetch;
}

- if (transaction != dbb->dbb_sys_trans)
+ if (transaction != dbb->dbb_sys_trans && transaction->tra_save_point)
++transaction->tra_save_point->sav_verb_count;

/* Handle pre-operation trigger */
@@ -1372,9 +1372,8 @@ static jrd_nod* erase(thread_db* tdbb, j
request->req_records_affected.bumpModified(true);
}

- if (transaction != dbb->dbb_sys_trans) {
+ if (transaction != dbb->dbb_sys_trans && transaction->tra_save_point)
--transaction->tra_save_point->sav_verb_count;
- }

rpb\-\>rpb\_number\.setValid\(false\);

@@ -3009,7 +3008,7 @@ static jrd_nod* modify(thread_db* tdbb,
varchar field whose tail may contain garbage. */
cleanup_rpb(tdbb, new_rpb);

- if (transaction != dbb->dbb_sys_trans)
+ if (transaction != dbb->dbb_sys_trans && transaction->tra_save_point)
++transaction->tra_save_point->sav_verb_count;

		PreModifyEraseTriggers\(tdbb, &relation\-\>rel\_pre\_modify, which\_trig, org\_rpb, new\_rpb,

@@ -3069,9 +3068,8 @@ static jrd_nod* modify(thread_db* tdbb,
}
}

- if (transaction != dbb->dbb_sys_trans) {
+ if (transaction != dbb->dbb_sys_trans && transaction->tra_save_point)
--transaction->tra_save_point->sav_verb_count;
- }

		/\* CVC: Increment the counter only if we called VIO/EXT\_modify\(\) and
				we were successful\. \*/

@@ -3790,7 +3788,7 @@ static jrd_nod* store(thread_db* tdbb, j
if (impure->sta_state)
return node->nod_parent;

- if (transaction != dbb->dbb_sys_trans)
+ if (transaction != dbb->dbb_sys_trans && transaction->tra_save_point)
++transaction->tra_save_point->sav_verb_count;

	if \(relation\-\>rel\_pre\_store && \(which\_trig \!= POST\_TRIG\) &&

@@ -3860,9 +3858,8 @@ static jrd_nod* store(thread_db* tdbb, j
request->req_records_affected.bumpModified(true);
}

- if (transaction != dbb->dbb_sys_trans) {
+ if (transaction != dbb->dbb_sys_trans && transaction->tra_save_point)
--transaction->tra_save_point->sav_verb_count;
- }

	if \(node\-\>nod\_arg\[e\_sto\_statement2\]\) \{
		impure\-\>sta\_state = 1;

@firebird-automations
Copy link
Collaborator Author

Commented by: @asfernandes

Hey, Vlad, as my patch didn't crash but rollbacks the inserted records :-), I'd say your is ok. ;-)

@firebird-automations
Copy link
Collaborator Author

Commented by: @hvlad

Good to hear that one of patches is ok ;)

I'm waiting for Dmitry's comment as he know savepoints code very well and could verify my patch.

@firebird-automations
Copy link
Collaborator Author

Commented by: @dyemanov

I agree with the patch.

@firebird-automations
Copy link
Collaborator Author

Modified by: @hvlad

assignee: Vlad Khorsun [ hvlad ]

@firebird-automations
Copy link
Collaborator Author

Modified by: @hvlad

status: Open [ 1 ] => Resolved [ 5 ]

resolution: Fixed [ 1 ]

Fix Version: 2.5 RC1 [ 10362 ]

@firebird-automations
Copy link
Collaborator Author

Modified by: @pcisar

status: Resolved [ 5 ] => Closed [ 6 ]

@firebird-automations
Copy link
Collaborator Author

Modified by: @pavel-zotov

QA Status: No test

@firebird-automations
Copy link
Collaborator Author

Modified by: @pavel-zotov

status: Closed [ 6 ] => Closed [ 6 ]

QA Status: No test => Not enough information

Test Details: "Could not find the specified attachment on the server"

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment