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(); 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; ISC_STATUS_ARRAY status;
e.stuff_exception(status); e.stuff_exception(status);
uSvc->initStatus();
uSvc->setServiceStatus(status); uSvc->setServiceStatus(status);
uSvc->started();
exit_code = FB_FAILURE; exit_code = FB_FAILURE;
} }
@ -494,7 +494,6 @@ int alice(Firebird::UtilSvc* uSvc)
if (uSvc->isService()) if (uSvc->isService())
{ {
uSvc->setServiceStatus(ALICE_MSG_FAC, 20, MsgFormat::SafeArg()); uSvc->setServiceStatus(ALICE_MSG_FAC, 20, MsgFormat::SafeArg());
uSvc->started();
} }
else else
{ {
@ -559,7 +558,7 @@ int alice(Firebird::UtilSvc* uSvc)
if (ret == FINI_ERROR) if (ret == FINI_ERROR)
{ {
ALICE_print_status(tdgbl->status); ALICE_print_status(true, tdgbl->status);
ALICE_exit(FINI_ERROR, tdgbl); ALICE_exit(FINI_ERROR, tdgbl);
} }
@ -577,12 +576,10 @@ int alice(Firebird::UtilSvc* uSvc)
{ {
// Non-alice exception was caught // Non-alice exception was caught
e.stuff_exception(tdgbl->status_vector); e.stuff_exception(tdgbl->status_vector);
ALICE_print_status(tdgbl->status_vector); ALICE_print_status(true, tdgbl->status_vector);
exit_code = FINI_ERROR; exit_code = FINI_ERROR;
} }
tdgbl->uSvc->started();
AliceGlobals::restoreSpecific(); AliceGlobals::restoreSpecific();
#if defined(DEBUG_GDS_ALLOC) #if defined(DEBUG_GDS_ALLOC)
@ -597,6 +594,7 @@ int alice(Firebird::UtilSvc* uSvc)
uSvc->initStatus(); uSvc->initStatus();
uSvc->setServiceStatus(tdgbl->status); uSvc->setServiceStatus(tdgbl->status);
} }
tdgbl->uSvc->started();
return exit_code; return exit_code;
} }
@ -627,7 +625,7 @@ void ALICE_print(USHORT number, const SafeArg& arg)
TEXT buffer[256]; TEXT buffer[256];
fb_msg_format(0, ALICE_MSG_FAC, number, sizeof(buffer), buffer, arg); 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. // 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]) if (status_vector && status_vector[1])
{ {
@ -645,15 +643,20 @@ void ALICE_print_status(const ISC_STATUS* status_vector)
AliceGlobals* tdgbl = AliceGlobals::getSpecific(); AliceGlobals* tdgbl = AliceGlobals::getSpecific();
tdgbl->uSvc->setServiceStatus(status_vector); tdgbl->uSvc->setServiceStatus(status_vector);
if (error && tdgbl->uSvc->isService())
{
return;
}
SCHAR s[1024]; SCHAR s[1024];
if (fb_interpret(s, sizeof(s), &vector)) if (fb_interpret(s, sizeof(s), &vector))
{ {
alice_output("%s\n", s); alice_output(error, "%s\n", s);
// Continuation of error // Continuation of error
s[0] = '-'; s[0] = '-';
while (fb_interpret(s + 1, sizeof(s) - 1, &vector)) { 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]; TEXT buffer[256];
tdgbl->uSvc->setServiceStatus(ALICE_MSG_FAC, number, arg); 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); ALICE_exit(FINI_ERROR, tdgbl);
} }
@ -683,7 +689,7 @@ void ALICE_error(USHORT number, const SafeArg& arg)
// Platform independent output routine. // Platform independent output routine.
// //
static void alice_output(const SCHAR* format, ...) static void alice_output(bool error, const SCHAR* format, ...)
{ {
AliceGlobals* tdgbl = AliceGlobals::getSpecific(); AliceGlobals* tdgbl = AliceGlobals::getSpecific();
@ -694,6 +700,9 @@ static void alice_output(const SCHAR* format, ...)
buf.vprintf(format, arglist); buf.vprintf(format, arglist);
va_end(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());
} }

View File

@ -76,7 +76,7 @@ static const rfr_tab_t rfr_table[] =
static inline void return_error(const ISC_STATUS* /*user_status*/) static inline void return_error(const ISC_STATUS* /*user_status*/)
{ {
ALICE_print_status(gds_status); ALICE_print_status(true, gds_status);
Firebird::LongJump::raise(); Firebird::LongJump::raise();
} }
@ -315,7 +315,7 @@ static tdr* get_description(ISC_QUAD* blob_id)
tdgbl->status[1] = isc_virmemexh; tdgbl->status[1] = isc_virmemexh;
tdgbl->status[2] = isc_arg_end; tdgbl->status[2] = isc_arg_end;
ALICE_print_status(tdgbl->status); ALICE_print_status(true, tdgbl->status);
return NULL; return NULL;
} }
snarf_blob(blob_id, length, bigger_buffer); 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; FB_API_HANDLE blob = 0;
if (isc_open_blob(gds_status, &DB, &gds_trans, &blob, blob_id)) 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; return 0;
} }

View File

@ -36,7 +36,7 @@ class AliceGlobals;
void ALICE_down_case(const TEXT*, TEXT*, const size_t); void ALICE_down_case(const TEXT*, TEXT*, const size_t);
void ALICE_print(USHORT, const MsgFormat::SafeArg& arg = MsgFormat::SafeArg()); void ALICE_print(USHORT, const MsgFormat::SafeArg& arg = MsgFormat::SafeArg());
void ALICE_error(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*); void ALICE_exit(int, AliceGlobals*);
#endif // ALICE_ALICE_PROTO_H #endif // ALICE_ALICE_PROTO_H

View File

@ -87,8 +87,6 @@ int EXE_action(const TEXT* database, const SINT64 switches)
dpb.getBufferLength(), dpb.getBufferLength(),
reinterpret_cast<const SCHAR*>(dpb.getBuffer())); reinterpret_cast<const SCHAR*>(dpb.getBuffer()));
tdgbl->uSvc->started();
if (tdgbl->status[1] && if (tdgbl->status[1] &&
// Ignore isc_shutdown error produced when we switch to full shutdown mode. It is expected. // Ignore isc_shutdown error produced when we switch to full shutdown mode. It is expected.
(tdgbl->status[1] != isc_shutdown || !(switches & sw_shut) || (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) if (tdgbl->status[2] == isc_arg_warning)
{ {
Firebird::makePermanentVector(tdgbl->status); Firebird::makePermanentVector(tdgbl->status);
ALICE_print_status(tdgbl->status); ALICE_print_status(false, tdgbl->status);
} }
else if (error) else if (error)
{ {
@ -126,6 +124,11 @@ int EXE_action(const TEXT* database, const SINT64 switches)
isc_detach_database(tdgbl->status, &handle); isc_detach_database(tdgbl->status, &handle);
} }
if (error)
{
tdgbl->uSvc->setServiceStatus(tdgbl->status);
}
} }
return error ? FINI_ERROR : FINI_OK; 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); error = TDR_reconnect_multiple(handle, tdgbl->ALICE_data.ua_transaction, database, switches);
} }
if (error)
{
Firebird::makePermanentVector(tdgbl->status);
}
if (handle) if (handle)
{ {
isc_detach_database(tdgbl->status, &handle); isc_detach_database(tdgbl->status, &handle);
} }
if (error)
{
tdgbl->uSvc->setServiceStatus(tdgbl->status);
}
} }
return (error ? FINI_ERROR : FINI_OK); 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) if (tdgbl->ALICE_data.ua_debug)
{ {
ALICE_print(69); // msg 69: failed ALICE_print(69); // msg 69: failed
ALICE_print_status(status_vector); ALICE_print_status(false, status_vector);
} }
return false; return false;
} }
@ -297,7 +297,7 @@ void TDR_list_limbo(FB_API_HANDLE handle, const TEXT* name, const SINT64 switche
sizeof(buffer), sizeof(buffer),
reinterpret_cast<char*>(buffer))) reinterpret_cast<char*>(buffer)))
{ {
ALICE_print_status(status_vector); ALICE_print_status(true, status_vector);
return; return;
} }
@ -832,7 +832,7 @@ static bool reconnect(FB_API_HANDLE handle, SLONG number, const TEXT* name, SINT
{ {
ALICE_print(90, SafeArg() << name); ALICE_print(90, SafeArg() << name);
// msg 90: failed to reconnect to a transaction in database %s // msg 90: failed to reconnect to a transaction in database %s
ALICE_print_status(status_vector); ALICE_print_status(false, status_vector);
return true; return true;
} }
@ -858,7 +858,7 @@ static bool reconnect(FB_API_HANDLE handle, SLONG number, const TEXT* name, SINT
if (status_vector[1]) if (status_vector[1])
{ {
ALICE_print_status(status_vector); ALICE_print_status(false, status_vector);
return true; return true;
} }

View File

@ -85,6 +85,12 @@ void StatusVector::ImplStatusVector::clear() throw()
m_status_vector[0] = isc_arg_end; 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() void StatusVector::ImplStatusVector::append(const StatusVector& v) throw()
{ {
ImplStatusVector newVector(getKind(), getCode()); ImplStatusVector newVector(getKind(), getCode());

View File

@ -71,6 +71,8 @@ protected:
virtual void shiftLeft(const AbstractString&) throw() { } virtual void shiftLeft(const AbstractString&) throw() { }
virtual void shiftLeft(const MetaName&) 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) { } ImplBase(ISC_STATUS k, ISC_STATUS c) throw() : kind(k), code(c) { }
virtual ~ImplBase() { } virtual ~ImplBase() { }
}; };
@ -113,6 +115,8 @@ protected:
virtual void shiftLeft(const AbstractString& text) throw(); virtual void shiftLeft(const AbstractString& text) throw();
virtual void shiftLeft(const MetaName& 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) ImplStatusVector(ISC_STATUS k, ISC_STATUS c) throw() : ImplBase(k, c)
{ {
clear(); clear();
@ -170,6 +174,16 @@ public:
return *this; return *this;
} }
bool operator==(const StatusVector& arg) const throw()
{
return implementation->compare(arg);
}
bool operator!=(const StatusVector& arg) const throw()
{
return !(*this == arg);
}
private: private:
}; };

View File

@ -514,9 +514,12 @@ void Service::setServiceStatus(const ISC_STATUS* status_vector)
{ {
Arg::StatusVector svc(svc_status); Arg::StatusVector svc(svc_status);
Arg::StatusVector passed(status_vector); Arg::StatusVector passed(status_vector);
svc.append(passed); if (svc != passed)
svc.copyTo(svc_status); {
makePermanentStatusVector(); svc.append(passed);
svc.copyTo(svc_status);
makePermanentStatusVector();
}
} }
} }