From 2689670200fba6fc675847dbb8cdac89e9095f39 Mon Sep 17 00:00:00 2001 From: alexpeshkoff Date: Tue, 4 Oct 2011 13:19:56 +0000 Subject: [PATCH] Backported fix for CORE-3612: gfix-related services may loose error value in status vector in isc_service_start() --- src/alice/alice.cpp | 39 ++++++++++++++++++++++++--------------- src/alice/alice_meta.epp | 6 +++--- src/alice/alice_proto.h | 2 +- src/alice/exe.cpp | 19 +++++++++++-------- src/alice/tdr.cpp | 8 ++++---- src/common/StatusArg.cpp | 6 ++++++ src/common/StatusArg.h | 14 ++++++++++++++ src/jrd/svc.cpp | 9 ++++++--- 8 files changed, 69 insertions(+), 34 deletions(-) diff --git a/src/alice/alice.cpp b/src/alice/alice.cpp index 24e1bcd901..a1854b350c 100644 --- a/src/alice/alice.cpp +++ b/src/alice/alice.cpp @@ -84,7 +84,7 @@ void ALICE_exit(int code, AliceGlobals* tdgbl) Firebird::LongJump::raise(); } -static void alice_output(const SCHAR*, ...) ATTRIBUTE_FORMAT(1,2); +static void alice_output(bool error, const SCHAR*, ...) ATTRIBUTE_FORMAT(2,3); @@ -105,8 +105,8 @@ THREAD_ENTRY_DECLARE ALICE_main(THREAD_ENTRY_PARAM arg) { ISC_STATUS_ARRAY status; e.stuff_exception(status); - uSvc->initStatus(); uSvc->setServiceStatus(status); + uSvc->started(); exit_code = FB_FAILURE; } @@ -494,7 +494,6 @@ int alice(Firebird::UtilSvc* uSvc) if (uSvc->isService()) { uSvc->setServiceStatus(ALICE_MSG_FAC, 20, MsgFormat::SafeArg()); - uSvc->started(); } else { @@ -559,7 +558,7 @@ int alice(Firebird::UtilSvc* uSvc) if (ret == FINI_ERROR) { - ALICE_print_status(tdgbl->status); + ALICE_print_status(true, tdgbl->status); ALICE_exit(FINI_ERROR, tdgbl); } @@ -577,12 +576,10 @@ int alice(Firebird::UtilSvc* uSvc) { // Non-alice exception was caught e.stuff_exception(tdgbl->status_vector); - ALICE_print_status(tdgbl->status_vector); + ALICE_print_status(true, tdgbl->status_vector); exit_code = FINI_ERROR; } - tdgbl->uSvc->started(); - AliceGlobals::restoreSpecific(); #if defined(DEBUG_GDS_ALLOC) @@ -597,6 +594,7 @@ int alice(Firebird::UtilSvc* uSvc) uSvc->initStatus(); uSvc->setServiceStatus(tdgbl->status); } + tdgbl->uSvc->started(); return exit_code; } @@ -627,7 +625,7 @@ void ALICE_print(USHORT number, const SafeArg& arg) TEXT buffer[256]; fb_msg_format(0, ALICE_MSG_FAC, number, sizeof(buffer), buffer, arg); - alice_output("%s\n", buffer); + alice_output(false, "%s\n", buffer); } @@ -637,7 +635,7 @@ void ALICE_print(USHORT number, const SafeArg& arg) // to allow redirecting output. // -void ALICE_print_status(const ISC_STATUS* status_vector) +void ALICE_print_status(bool error, const ISC_STATUS* status_vector) { if (status_vector && status_vector[1]) { @@ -645,15 +643,20 @@ void ALICE_print_status(const ISC_STATUS* status_vector) AliceGlobals* tdgbl = AliceGlobals::getSpecific(); tdgbl->uSvc->setServiceStatus(status_vector); + if (error && tdgbl->uSvc->isService()) + { + return; + } + SCHAR s[1024]; if (fb_interpret(s, sizeof(s), &vector)) { - alice_output("%s\n", s); + alice_output(error, "%s\n", s); // Continuation of error s[0] = '-'; while (fb_interpret(s + 1, sizeof(s) - 1, &vector)) { - alice_output("%s\n", s); + alice_output(error, "%s\n", s); } } } @@ -671,9 +674,12 @@ void ALICE_error(USHORT number, const SafeArg& arg) TEXT buffer[256]; tdgbl->uSvc->setServiceStatus(ALICE_MSG_FAC, number, arg); + if (!tdgbl->uSvc->isService()) + { + fb_msg_format(0, ALICE_MSG_FAC, number, sizeof(buffer), buffer, arg); + alice_output(true, "%s\n", buffer); + } - fb_msg_format(0, ALICE_MSG_FAC, number, sizeof(buffer), buffer, arg); - alice_output("%s\n", buffer); ALICE_exit(FINI_ERROR, tdgbl); } @@ -683,7 +689,7 @@ void ALICE_error(USHORT number, const SafeArg& arg) // Platform independent output routine. // -static void alice_output(const SCHAR* format, ...) +static void alice_output(bool error, const SCHAR* format, ...) { AliceGlobals* tdgbl = AliceGlobals::getSpecific(); @@ -694,6 +700,9 @@ static void alice_output(const SCHAR* format, ...) buf.vprintf(format, arglist); va_end(arglist); - tdgbl->uSvc->outputError(buf.c_str()); + if (error) + tdgbl->uSvc->outputError(buf.c_str()); + else + tdgbl->uSvc->outputVerbose(buf.c_str()); } diff --git a/src/alice/alice_meta.epp b/src/alice/alice_meta.epp index c248333035..4c9324f907 100644 --- a/src/alice/alice_meta.epp +++ b/src/alice/alice_meta.epp @@ -76,7 +76,7 @@ static const rfr_tab_t rfr_table[] = static inline void return_error(const ISC_STATUS* /*user_status*/) { - ALICE_print_status(gds_status); + ALICE_print_status(true, gds_status); Firebird::LongJump::raise(); } @@ -315,7 +315,7 @@ static tdr* get_description(ISC_QUAD* blob_id) tdgbl->status[1] = isc_virmemexh; tdgbl->status[2] = isc_arg_end; - ALICE_print_status(tdgbl->status); + ALICE_print_status(true, tdgbl->status); return NULL; } snarf_blob(blob_id, length, bigger_buffer); @@ -479,7 +479,7 @@ static USHORT snarf_blob(ISC_QUAD* blob_id, USHORT buffer_length, TEXT* buffer) FB_API_HANDLE blob = 0; if (isc_open_blob(gds_status, &DB, &gds_trans, &blob, blob_id)) { - ALICE_print_status(gds_status); + ALICE_print_status(true, gds_status); return 0; } diff --git a/src/alice/alice_proto.h b/src/alice/alice_proto.h index 75ce687ffd..c69356751e 100644 --- a/src/alice/alice_proto.h +++ b/src/alice/alice_proto.h @@ -36,7 +36,7 @@ class AliceGlobals; void ALICE_down_case(const TEXT*, TEXT*, const size_t); void ALICE_print(USHORT, const MsgFormat::SafeArg& arg = MsgFormat::SafeArg()); void ALICE_error(USHORT, const MsgFormat::SafeArg& arg = MsgFormat::SafeArg()); -void ALICE_print_status(const ISC_STATUS*); +void ALICE_print_status(bool error, const ISC_STATUS*); void ALICE_exit(int, AliceGlobals*); #endif // ALICE_ALICE_PROTO_H diff --git a/src/alice/exe.cpp b/src/alice/exe.cpp index e793364c81..98fa195497 100644 --- a/src/alice/exe.cpp +++ b/src/alice/exe.cpp @@ -87,8 +87,6 @@ int EXE_action(const TEXT* database, const SINT64 switches) dpb.getBufferLength(), reinterpret_cast(dpb.getBuffer())); - tdgbl->uSvc->started(); - if (tdgbl->status[1] && // Ignore isc_shutdown error produced when we switch to full shutdown mode. It is expected. (tdgbl->status[1] != isc_shutdown || !(switches & sw_shut) || @@ -100,7 +98,7 @@ int EXE_action(const TEXT* database, const SINT64 switches) if (tdgbl->status[2] == isc_arg_warning) { Firebird::makePermanentVector(tdgbl->status); - ALICE_print_status(tdgbl->status); + ALICE_print_status(false, tdgbl->status); } else if (error) { @@ -126,6 +124,11 @@ int EXE_action(const TEXT* database, const SINT64 switches) isc_detach_database(tdgbl->status, &handle); } + + if (error) + { + tdgbl->uSvc->setServiceStatus(tdgbl->status); + } } return error ? FINI_ERROR : FINI_OK; @@ -173,15 +176,15 @@ int EXE_two_phase(const TEXT* database, const SINT64 switches) error = TDR_reconnect_multiple(handle, tdgbl->ALICE_data.ua_transaction, database, switches); } - if (error) - { - Firebird::makePermanentVector(tdgbl->status); - } - if (handle) { isc_detach_database(tdgbl->status, &handle); } + + if (error) + { + tdgbl->uSvc->setServiceStatus(tdgbl->status); + } } return (error ? FINI_ERROR : FINI_OK); diff --git a/src/alice/tdr.cpp b/src/alice/tdr.cpp index aec7ef5c5f..cc08ecf473 100644 --- a/src/alice/tdr.cpp +++ b/src/alice/tdr.cpp @@ -227,7 +227,7 @@ bool TDR_attach_database(ISC_STATUS* status_vector, tdr* trans, const TEXT* path if (tdgbl->ALICE_data.ua_debug) { ALICE_print(69); // msg 69: failed - ALICE_print_status(status_vector); + ALICE_print_status(false, status_vector); } return false; } @@ -297,7 +297,7 @@ void TDR_list_limbo(FB_API_HANDLE handle, const TEXT* name, const SINT64 switche sizeof(buffer), reinterpret_cast(buffer))) { - ALICE_print_status(status_vector); + ALICE_print_status(true, status_vector); return; } @@ -832,7 +832,7 @@ static bool reconnect(FB_API_HANDLE handle, SLONG number, const TEXT* name, SINT { ALICE_print(90, SafeArg() << name); // msg 90: failed to reconnect to a transaction in database %s - ALICE_print_status(status_vector); + ALICE_print_status(false, status_vector); return true; } @@ -858,7 +858,7 @@ static bool reconnect(FB_API_HANDLE handle, SLONG number, const TEXT* name, SINT if (status_vector[1]) { - ALICE_print_status(status_vector); + ALICE_print_status(false, status_vector); return true; } diff --git a/src/common/StatusArg.cpp b/src/common/StatusArg.cpp index 5a1c7693d2..4f7aa63ad4 100644 --- a/src/common/StatusArg.cpp +++ b/src/common/StatusArg.cpp @@ -85,6 +85,12 @@ void StatusVector::ImplStatusVector::clear() throw() m_status_vector[0] = isc_arg_end; } +bool StatusVector::ImplStatusVector::compare(const StatusVector& v) const throw() +{ + return m_length == v.length() && + memcmp(m_status_vector, v.value(), m_length * sizeof(ISC_STATUS)) == 0; +} + void StatusVector::ImplStatusVector::append(const StatusVector& v) throw() { ImplStatusVector newVector(getKind(), getCode()); diff --git a/src/common/StatusArg.h b/src/common/StatusArg.h index 72c41e0fdc..8bfeee9b15 100644 --- a/src/common/StatusArg.h +++ b/src/common/StatusArg.h @@ -71,6 +71,8 @@ protected: virtual void shiftLeft(const AbstractString&) throw() { } virtual void shiftLeft(const MetaName&) throw() { } + virtual bool compare(const StatusVector& v) const throw() { return false; } + ImplBase(ISC_STATUS k, ISC_STATUS c) throw() : kind(k), code(c) { } virtual ~ImplBase() { } }; @@ -113,6 +115,8 @@ protected: virtual void shiftLeft(const AbstractString& text) throw(); virtual void shiftLeft(const MetaName& text) throw(); + virtual bool compare(const StatusVector& v) const throw(); + ImplStatusVector(ISC_STATUS k, ISC_STATUS c) throw() : ImplBase(k, c) { clear(); @@ -170,6 +174,16 @@ public: return *this; } + bool operator==(const StatusVector& arg) const throw() + { + return implementation->compare(arg); + } + + bool operator!=(const StatusVector& arg) const throw() + { + return !(*this == arg); + } + private: }; diff --git a/src/jrd/svc.cpp b/src/jrd/svc.cpp index 370b08d1c8..2bb8a52511 100644 --- a/src/jrd/svc.cpp +++ b/src/jrd/svc.cpp @@ -514,9 +514,12 @@ void Service::setServiceStatus(const ISC_STATUS* status_vector) { Arg::StatusVector svc(svc_status); Arg::StatusVector passed(status_vector); - svc.append(passed); - svc.copyTo(svc_status); - makePermanentStatusVector(); + if (svc != passed) + { + svc.append(passed); + svc.copyTo(svc_status); + makePermanentStatusVector(); + } } }