8
0
mirror of https://github.com/FirebirdSQL/firebird.git synced 2025-01-24 06:43:03 +01:00

Backported fix for CORE-3612: gfix-related services may loose error value in status vector in isc_service_start()

This commit is contained in:
alexpeshkoff 2011-10-04 13:19:56 +00:00
parent b42ce8e27b
commit 2689670200
8 changed files with 69 additions and 34 deletions

View File

@ -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("%s\n", buffer);
alice_output(true, "%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);
if (error)
tdgbl->uSvc->outputError(buf.c_str());
else
tdgbl->uSvc->outputVerbose(buf.c_str());
}

View File

@ -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;
}

View File

@ -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

View File

@ -87,8 +87,6 @@ int EXE_action(const TEXT* database, const SINT64 switches)
dpb.getBufferLength(),
reinterpret_cast<const SCHAR*>(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);

View File

@ -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<char*>(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;
}

View File

@ -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());

View File

@ -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:
};

View File

@ -514,10 +514,13 @@ void Service::setServiceStatus(const ISC_STATUS* status_vector)
{
Arg::StatusVector svc(svc_status);
Arg::StatusVector passed(status_vector);
if (svc != passed)
{
svc.append(passed);
svc.copyTo(svc_status);
makePermanentStatusVector();
}
}
}
void Service::setServiceStatus(const USHORT facility, const USHORT errcode, const MsgFormat::SafeArg& args)