From df6706bb4b78fb50e670be64909359834de2d542 Mon Sep 17 00:00:00 2001 From: dimitr Date: Mon, 10 Dec 2007 07:21:27 +0000 Subject: [PATCH] Fixed CORE-1610 and its subtask CORE-1615. --- src/jrd/jrd.cpp | 117 +++++++++++++++++++++++++----------------------- src/jrd/jrd.h | 1 + src/jrd/vio.cpp | 3 ++ 3 files changed, 66 insertions(+), 55 deletions(-) diff --git a/src/jrd/jrd.cpp b/src/jrd/jrd.cpp index 7d6b3d0bd7..02978db09d 100644 --- a/src/jrd/jrd.cpp +++ b/src/jrd/jrd.cpp @@ -4467,78 +4467,85 @@ bool JRD_reschedule(thread_db* tdbb, SLONG quantum, bool punt) THREAD_ENTER(); } -/* If database has been shutdown then get out */ + // Test various flags and unwind/throw if required. + // But do that only if we're not in the verb cleanup state, + // which should never be interrupted. - Database* dbb = tdbb->tdbb_database; - Attachment* attachment = tdbb->tdbb_attachment; - if (attachment) + if (!(tdbb->tdbb_flags & TDBB_verb_cleanup)) { - Firebird::PathName file_name = attachment->att_filename; + /* If database has been shutdown then get out */ - if (dbb->dbb_ast_flags & DBB_shutdown && - attachment->att_flags & ATT_shutdown) + Database* dbb = tdbb->tdbb_database; + Attachment* attachment = tdbb->tdbb_attachment; + if (attachment) { - if (punt) { - CCH_unwind(tdbb, false); - ERR_post(isc_shutdown, isc_arg_string, - ERR_cstring(file_name), 0); - } - else { - ISC_STATUS* status = tdbb->tdbb_status_vector; - *status++ = isc_arg_gds; - *status++ = isc_shutdown; - *status++ = isc_arg_string; - *status++ = (ISC_STATUS) ERR_cstring(file_name); - *status++ = isc_arg_end; - return true; - } - } - else if (attachment->att_flags & ATT_shutdown && - !(tdbb->tdbb_flags & TDBB_shutdown_manager)) - { - if (punt) { - CCH_unwind(tdbb, false); - ERR_post(isc_att_shutdown, 0); - } - else { - ISC_STATUS* status = tdbb->tdbb_status_vector; - *status++ = isc_arg_gds; - *status++ = isc_att_shutdown; - *status++ = isc_arg_end; - return true; - } - } -#ifdef CANCEL_OPERATION + Firebird::PathName file_name = attachment->att_filename; - /* If a cancel has been raised, defer its acknowledgement - when executing in the context of an internal request or - the system transaction. */ - - if ((attachment->att_flags & ATT_cancel_raise) && - !(attachment->att_flags & ATT_cancel_disable)) - { - const jrd_tra* transaction; - jrd_req* request = tdbb->tdbb_request; - if ((!request || - !(request->req_flags & (req_internal | req_sys_trigger))) && - (!(transaction = tdbb->tdbb_transaction) || - !(transaction->tra_flags & TRA_system))) + if (dbb->dbb_ast_flags & DBB_shutdown && + attachment->att_flags & ATT_shutdown) { - attachment->att_flags &= ~ATT_cancel_raise; if (punt) { CCH_unwind(tdbb, false); - ERR_post(isc_cancelled, 0); + ERR_post(isc_shutdown, isc_arg_string, + ERR_cstring(file_name), 0); } else { ISC_STATUS* status = tdbb->tdbb_status_vector; *status++ = isc_arg_gds; - *status++ = isc_cancelled; + *status++ = isc_shutdown; + *status++ = isc_arg_string; + *status++ = (ISC_STATUS) ERR_cstring(file_name); *status++ = isc_arg_end; return true; } } + else if (attachment->att_flags & ATT_shutdown && + !(tdbb->tdbb_flags & TDBB_shutdown_manager)) + { + if (punt) { + CCH_unwind(tdbb, false); + ERR_post(isc_att_shutdown, 0); + } + else { + ISC_STATUS* status = tdbb->tdbb_status_vector; + *status++ = isc_arg_gds; + *status++ = isc_att_shutdown; + *status++ = isc_arg_end; + return true; + } + } + #ifdef CANCEL_OPERATION + + /* If a cancel has been raised, defer its acknowledgement + when executing in the context of an internal request or + the system transaction. */ + + if ((attachment->att_flags & ATT_cancel_raise) && + !(attachment->att_flags & ATT_cancel_disable)) + { + const jrd_tra* transaction; + jrd_req* request = tdbb->tdbb_request; + if ((!request || + !(request->req_flags & (req_internal | req_sys_trigger))) && + (!(transaction = tdbb->tdbb_transaction) || + !(transaction->tra_flags & TRA_system))) + { + attachment->att_flags &= ~ATT_cancel_raise; + if (punt) { + CCH_unwind(tdbb, false); + ERR_post(isc_cancelled, 0); + } + else { + ISC_STATUS* status = tdbb->tdbb_status_vector; + *status++ = isc_arg_gds; + *status++ = isc_cancelled; + *status++ = isc_arg_end; + return true; + } + } + } + #endif } -#endif } tdbb->tdbb_quantum = (tdbb->tdbb_quantum <= 0) ? diff --git a/src/jrd/jrd.h b/src/jrd/jrd.h index cecb771ba9..f40ccfea7a 100644 --- a/src/jrd/jrd.h +++ b/src/jrd/jrd.h @@ -1042,6 +1042,7 @@ const USHORT TDBB_set_backup_state = 8; /* Setting state for backup lock */ const USHORT TDBB_backup_merge = 16; /* Merging changes from difference file */ const USHORT TDBB_stack_trace_done = 32; /* PSQL stack trase is added into status-vector */ const USHORT TDBB_shutdown_manager = 64; /* Server shutdown thread */ +const USHORT TDBB_verb_cleanup = 128; /* Verb cleanup is in progress */ // duplicate context of firebird string to store in jrd_nod::nod_arg diff --git a/src/jrd/vio.cpp b/src/jrd/vio.cpp index a9771cf104..57bb71243e 100644 --- a/src/jrd/vio.cpp +++ b/src/jrd/vio.cpp @@ -2897,6 +2897,7 @@ void VIO_verb_cleanup(thread_db* tdbb, jrd_tra* transaction) VerbAction* action; jrd_tra* old_tran = tdbb->tdbb_transaction; try { + tdbb->tdbb_flags |= TDBB_verb_cleanup; tdbb->tdbb_transaction = transaction; while ( (action = sav_point->sav_verb_actions) ) { @@ -3044,9 +3045,11 @@ void VIO_verb_cleanup(thread_db* tdbb, jrd_tra* transaction) delete action; } tdbb->tdbb_transaction = old_tran; + tdbb->tdbb_flags &= ~TDBB_verb_cleanup; } catch (...) { tdbb->tdbb_transaction = old_tran; + tdbb->tdbb_flags &= ~TDBB_verb_cleanup; throw; }