Skip to content

Commit

Permalink
Fixed problems with shutting down actively running engine - related w…
Browse files Browse the repository at this point in the history
…ith CORE-1805.
  • Loading branch information
AlexPeshkoff committed Apr 2, 2008
1 parent bc5c242 commit aafed20
Show file tree
Hide file tree
Showing 10 changed files with 273 additions and 86 deletions.
12 changes: 10 additions & 2 deletions src/alice/alice.cpp
Expand Up @@ -98,10 +98,18 @@ static void alice_output(const SCHAR*, ...) ATTRIBUTE_FORMAT(1,2);
THREAD_ENTRY_DECLARE ALICE_main(THREAD_ENTRY_PARAM arg)
{
Firebird::UtilSvc* uSvc = (Firebird::UtilSvc*) arg;
const int exit_code = alice(uSvc);
int exit_code = FB_SUCCESS;

uSvc->finish();
try {
exit_code = alice(uSvc);
}
catch (const Firebird::Exception& e)
{
e.stuff_exception(uSvc->getStatus());
exit_code = FB_FAILURE;
}

uSvc->finish();
return (THREAD_ENTRY_RETURN)(IPTR) exit_code;
}

Expand Down
14 changes: 10 additions & 4 deletions src/burp/burp.cpp
Expand Up @@ -128,12 +128,18 @@ THREAD_ENTRY_DECLARE BURP_main(THREAD_ENTRY_PARAM arg)
*
**************************************/
Firebird::UtilSvc* uSvc = (Firebird::UtilSvc*) arg;
const int exit_code = gbak(uSvc);
int exit_code = FB_SUCCESS;

// Mark service thread as finished.
// If service is detached, cleanup memory being used by service.
uSvc->finish();
try {
exit_code = gbak(uSvc);
}
catch (const Firebird::Exception& e)
{
e.stuff_exception(uSvc->getStatus());
exit_code = FB_FAILURE;
}

uSvc->finish();
return (THREAD_ENTRY_RETURN)(IPTR) exit_code;
}

Expand Down
4 changes: 4 additions & 0 deletions src/common/classes/fb_atomic.h
Expand Up @@ -129,6 +129,10 @@ class AtomicCounter
namespace Firebird {

// Highly inefficient, but safe and portable implementation
// We keep it for DEV build to start doing ports, bus should avoid in release
#ifndef DEV_BUILD
#pragma FB_COMPILER_MESSAGE("Generic AtomicCounter: implement appropriate for your platform!"
#endif
class AtomicCounter
{
public:
Expand Down
6 changes: 5 additions & 1 deletion src/jrd/jrd.cpp
Expand Up @@ -464,7 +464,9 @@ static void check_autocommit(jrd_req* request, thread_db* tdbb)
{
// dimitr: we should ignore autocommit for requests
// created by EXECUTE STATEMENT
if (request->req_transaction->tra_callback_count > 0)
// AP: also do nothing if request is cancelled and
// transaction is already missing
if ((!request->req_transaction) || (request->req_transaction->tra_callback_count > 0))
return;

if (request->req_transaction->tra_flags & TRA_perform_autocommit)
Expand Down Expand Up @@ -5795,6 +5797,8 @@ static THREAD_ENTRY_DECLARE shutdown_thread(THREAD_ENTRY_PARAM arg)
break;
}
}

Service::shutdownServices();
}
catch (const Firebird::Exception&)
{
Expand Down
28 changes: 6 additions & 22 deletions src/jrd/os/posix/isc_ipc.cpp
Expand Up @@ -136,10 +136,6 @@ static void CLIB_ROUTINE signal_action(int number, siginfo_t *siginfo, void *con
#define SIG_HOLD SIG_DFL
#endif

// Not thread-safe

ULONG isc_enter_count = 0;

void ISC_enter(void)
{
/**************************************
Expand Down Expand Up @@ -440,26 +436,14 @@ static SLONG overflow_handler(void* arg)
fprintf(stderr, "overflow_handler (%x)\n", arg);
#endif

/* If we're within ISC world (inside why-value) when the FPE occurs
* we handle it (basically by ignoring it). If it occurs outside of
* ISC world, return back a code that tells signal_action to call any
* customer provided handler.
*/
if (isc_enter_count) {
++overflow_count;
++overflow_count;
#ifdef DEBUG_FPE_HANDLING
fprintf(stderr, "SIGFPE in isc code ignored %d\n",
overflow_count);
fprintf(stderr, "SIGFPE in isc code ignored %d\n",
overflow_count);
#endif
/* We've "handled" the FPE - let signal_action know not to chain
the signal to other handlers */
return SIG_informs_stop;
}
else {
/* We've NOT "handled" the FPE - let signal_action know to chain
the signal to other handlers */
return SIG_informs_continue;
}
/* We've "handled" the FPE - let signal_action know not to chain
the signal to other handlers */
return SIG_informs_stop;
}

static SIG que_signal(int signal_number,
Expand Down
124 changes: 108 additions & 16 deletions src/jrd/svc.cpp
Expand Up @@ -116,8 +116,9 @@ const int GET_BINARY = 4;
const TEXT SVC_TRMNTR = '\377';
const char* const SPB_SEC_USERNAME = "isc_spb_sec_username";

// Option block for service parameter block
namespace {

// Option block for service parameter block
struct Options {
Firebird::string spb_sys_user_name;
Firebird::string spb_user_name;
Expand Down Expand Up @@ -214,13 +215,20 @@ namespace {
}
}
};

// Generic mutex to synchronize services
Firebird::GlobalPtr<Firebird::Mutex> svc_mutex;

// All that we need to shutdown service threads when shutdown in progress
typedef Firebird::Array<Jrd::Service*> AllServices;
Firebird::GlobalPtr<AllServices> allServices; // protected by svc_mutex
volatile bool svcShutdown = false;

} // anonymous namespace


using namespace Jrd;

static Firebird::GlobalPtr<Firebird::Mutex> svc_mutex, thd_mutex;


void Service::parseSwitches()
{
Expand Down Expand Up @@ -306,6 +314,7 @@ void Service::started()
{
if (!(svc_flags & SVC_evnt_fired))
{
Firebird::MutexLockGuard guard(svc_mutex);
svc_flags |= SVC_evnt_fired;
svcStart.release();
}
Expand Down Expand Up @@ -347,6 +356,11 @@ void Service::putChar(char tag, char val)

void Service::stuffStatus(const ISC_STATUS* status_vector)
{
if (checkForShutdown())
{
return;
}

if (status_vector != svc_status)
{
ISC_STATUS* status = svc_status;
Expand All @@ -372,6 +386,11 @@ void Service::stuffStatus(const ISC_STATUS* status_vector)

void Service::stuffStatus(const USHORT facility, const USHORT errcode, const MsgFormat::SafeArg& args)
{
if (checkForShutdown())
{
return;
}

CMD_UTIL_put_svc_status(svc_status, facility, errcode, args);
}

Expand Down Expand Up @@ -426,19 +445,15 @@ void test_cmd(USHORT, SCHAR *, TEXT **);
#if !defined(BOOT_BUILD)
#include "../burp/burp_proto.h"
#include "../alice/alice_proto.h"
int main_lock_print();
THREAD_ENTRY_DECLARE main_gstat(THREAD_ENTRY_PARAM arg);

#define MAIN_GBAK BURP_main
#define MAIN_GFIX ALICE_main
#define MAIN_LOCK_PRINT main_lock_print
#define MAIN_GSTAT main_gstat
#else
#define MAIN_GBAK NULL
#define MAIN_GFIX NULL
#define MAIN_LOCK_PRINT NULL
#define MAIN_GSTAT NULL
#define MAIN_GSEC NULL
#endif

#if !defined(EMBEDDED) && !defined(BOOT_BUILD)
Expand Down Expand Up @@ -531,6 +546,13 @@ Service::Service(USHORT service_length, const TEXT* service_name,
{
memset(svc_status_array, 0, sizeof svc_status_array);

{
// Account service block in global array
Firebird::MutexLockGuard guard(svc_mutex);
checkForShutdown();
allServices->add(this);
}

// If the service name begins with a slash, ignore it.
if (*service_name == '/' || *service_name == '\\') {
service_name++;
Expand Down Expand Up @@ -658,7 +680,11 @@ void Service::detach()
{
if (svc_do_shutdown)
{
fb_shutdown(10 * 1000); // 10 seconds
if (fb_shutdown(10 * 1000 /* 10 seconds */) == FB_SUCCESS)
{
Firebird::InstanceControl::registerShutdown(0);
exit(0);
}
}

if (svc_uses_security_database)
Expand All @@ -676,6 +702,53 @@ Service::~Service()
#ifdef WIN_NT
CloseHandle((HANDLE) svc_handle);
#endif
Firebird::MutexLockGuard guard(svc_mutex);
AllServices& all(allServices);
for (unsigned int pos = 0; pos < all.getCount(); ++pos)
{
if (all[pos] == this)
{
all.remove(pos);
break;
}
}
}


bool Service::checkForShutdown()
{
if (svcShutdown)
{
Firebird::MutexLockGuard guard(svc_mutex);
if (svc_flags & SVC_shutdown)
{
// Here we avoid multiple exceptions thrown
return true;
}
svc_flags |= SVC_shutdown;
Firebird::status_exception::raise(isc_att_shutdown, isc_arg_end);
}
return false;
}


void Service::shutdownServices()
{
svcShutdown = true;
Firebird::MutexLockGuard guard(svc_mutex);
AllServices& all(allServices);
for (unsigned int pos = 0; pos < all.getCount(); )
{
if (all[pos]->svc_flags & SVC_thd_running)
{
svc_mutex->leave();
THD_sleep(1);
svc_mutex->enter();
pos = 0;
continue;
}
++pos;
}
}


Expand Down Expand Up @@ -1519,8 +1592,8 @@ void Service::start(USHORT spb_length, const UCHAR* spb_data)
Firebird::status_exception::raise(isc_bad_spb_form, 0);
}

{ // scope for locked thd_mutex
Firebird::MutexLockGuard guard(thd_mutex);
{ // scope for locked svc_mutex
Firebird::MutexLockGuard guard(svc_mutex);

if (svc_flags & SVC_thd_running) {
Firebird::status_exception::raise(isc_svc_in_use, isc_arg_string,
Expand All @@ -1536,7 +1609,6 @@ void Service::start(USHORT spb_length, const UCHAR* spb_data)
{
svc_flags = 0;
}
svc_flags |= SVC_thd_running;
}

if (!svc_perm_sw.hasData())
Expand Down Expand Up @@ -1623,7 +1695,11 @@ void Service::start(USHORT spb_length, const UCHAR* spb_data)
memset((void *) svc_status, 0, sizeof(ISC_STATUS_ARRAY));

if (serv->serv_thd) {
svc_flags &= ~SVC_evnt_fired;
{
Firebird::MutexLockGuard guard(svc_mutex);
svc_flags &= ~SVC_evnt_fired;
svc_flags |= SVC_thd_running;
}

gds__thread_start(serv->serv_thd, this, THREAD_medium, 0, (void *) &svc_handle);

Expand Down Expand Up @@ -1730,9 +1806,18 @@ UCHAR Service::dequeueByte()

void Service::enqueueByte(UCHAR ch)
{
if (checkForShutdown())
{
return;
}

// Wait for space in buffer while service is not detached.
while (full() && !(svc_flags & SVC_detached)) {
THREAD_SLEEP(1);
if (checkForShutdown())
{
return;
}
}

// Ensure that service is not detached.
Expand Down Expand Up @@ -1772,7 +1857,10 @@ void Service::get(SCHAR* buffer,
#endif

*return_length = 0;
svc_flags &= ~SVC_timeout;
{
Firebird::MutexLockGuard guard(svc_mutex);
svc_flags &= ~SVC_timeout;
}

while (length) {
if (empty())
Expand All @@ -1785,6 +1873,7 @@ void Service::get(SCHAR* buffer,
const time_t elapsed_time = end_time - start_time;
#endif
if ((timeout) && (elapsed_time >= timeout)) {
Firebird::MutexLockGuard guard(svc_mutex);
svc_flags &= SVC_timeout;
return;
}
Expand Down Expand Up @@ -1822,11 +1911,15 @@ void Service::finish(USHORT flag)
{
if (flag == SVC_finished || flag == SVC_detached)
{
svc_mutex->enter();
Firebird::MutexLockGuard guard(svc_mutex);

svc_flags |= flag;
if (! (svc_flags & SVC_thd_running))
{
svc_flags |= SVC_finished;
}
if (svc_flags & SVC_finished && svc_flags & SVC_detached)
{
svc_mutex->leave();
delete this;
return;
}
Expand All @@ -1839,7 +1932,6 @@ void Service::finish(USHORT flag)
#endif
svc_handle = 0;
}
svc_mutex->leave();
}
}

Expand Down

0 comments on commit aafed20

Please sign in to comment.