mirror of https://gitee.com/bigwinds/arangodb
fixed shutdown for busy V8 contexts
This commit is contained in:
parent
91e0f76082
commit
c8ddff2a9b
|
@ -761,6 +761,7 @@ void ArangoServer::buildApplicationServer () {
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
int ArangoServer::startupServer () {
|
int ArangoServer::startupServer () {
|
||||||
|
OperationMode::server_operation_mode_e mode = OperationMode::determineMode(_applicationServer->programOptions());
|
||||||
|
|
||||||
// .............................................................................
|
// .............................................................................
|
||||||
// prepare the various parts of the Arango server
|
// prepare the various parts of the Arango server
|
||||||
|
@ -783,8 +784,21 @@ int ArangoServer::startupServer () {
|
||||||
assert(vocbase != 0);
|
assert(vocbase != 0);
|
||||||
|
|
||||||
// initialise V8
|
// initialise V8
|
||||||
|
size_t concurrency = _dispatcherThreads;
|
||||||
|
|
||||||
|
if (mode == OperationMode::MODE_CONSOLE) {
|
||||||
|
// one V8 instance is taken by the console
|
||||||
|
++concurrency;
|
||||||
|
}
|
||||||
|
else if (mode == OperationMode::MODE_UNITTESTS || mode == OperationMode::MODE_SCRIPT) {
|
||||||
|
if (concurrency == 1) {
|
||||||
|
// at least two to allow the test-runner and the scheduler to use a V8
|
||||||
|
concurrency = 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
_applicationV8->setVocbase(vocbase);
|
_applicationV8->setVocbase(vocbase);
|
||||||
_applicationV8->setConcurrency(_dispatcherThreads);
|
_applicationV8->setConcurrency(concurrency);
|
||||||
|
|
||||||
if (_applicationServer->programOptions().has("upgrade")) {
|
if (_applicationServer->programOptions().has("upgrade")) {
|
||||||
_applicationV8->performUpgrade();
|
_applicationV8->performUpgrade();
|
||||||
|
@ -855,8 +869,6 @@ int ArangoServer::startupServer () {
|
||||||
|
|
||||||
LOG_INFO("ArangoDB (version " TRI_VERSION_FULL ") is ready for business. Have fun!");
|
LOG_INFO("ArangoDB (version " TRI_VERSION_FULL ") is ready for business. Have fun!");
|
||||||
|
|
||||||
OperationMode::server_operation_mode_e mode = OperationMode::determineMode(_applicationServer->programOptions());
|
|
||||||
|
|
||||||
int res;
|
int res;
|
||||||
|
|
||||||
if (mode == OperationMode::MODE_CONSOLE) {
|
if (mode == OperationMode::MODE_CONSOLE) {
|
||||||
|
|
|
@ -90,19 +90,20 @@ void ConsoleThread::run () {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
inner();
|
inner();
|
||||||
_applicationV8->exitContext(_context);
|
|
||||||
_done = 1;
|
|
||||||
}
|
}
|
||||||
catch (const char*) {
|
catch (const char*) {
|
||||||
_applicationV8->exitContext(_context);
|
|
||||||
_done = 1;
|
|
||||||
}
|
}
|
||||||
catch (...) {
|
catch (...) {
|
||||||
_applicationV8->exitContext(_context);
|
_applicationV8->exitContext(_context);
|
||||||
_done = 1;
|
_done = 1;
|
||||||
|
_applicationServer->beginShutdown();
|
||||||
|
|
||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_applicationV8->exitContext(_context);
|
||||||
|
_done = 1;
|
||||||
|
_applicationServer->beginShutdown();
|
||||||
}
|
}
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
@ -156,7 +157,6 @@ void ConsoleThread::inner () {
|
||||||
|
|
||||||
if (input == 0) {
|
if (input == 0) {
|
||||||
_userAborted = true;
|
_userAborted = true;
|
||||||
_applicationServer->beginShutdown();
|
|
||||||
|
|
||||||
// this will be caught by "run"
|
// this will be caught by "run"
|
||||||
throw "user aborted";
|
throw "user aborted";
|
||||||
|
|
|
@ -96,7 +96,6 @@ namespace triagens {
|
||||||
|
|
||||||
void userAbort () {
|
void userAbort () {
|
||||||
_userAborted = true;
|
_userAborted = true;
|
||||||
TRI_CLOSE(0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
|
@ -746,6 +746,25 @@ bool ApplicationV8::start () {
|
||||||
void ApplicationV8::close () {
|
void ApplicationV8::close () {
|
||||||
_stopping = 1;
|
_stopping = 1;
|
||||||
_contextCondition.broadcast();
|
_contextCondition.broadcast();
|
||||||
|
|
||||||
|
// unregister all tasks
|
||||||
|
if (_scheduler != nullptr) {
|
||||||
|
_scheduler->scheduler()->unregisterUserTasks();
|
||||||
|
}
|
||||||
|
|
||||||
|
// wait for all contexts to finish
|
||||||
|
for (size_t n = 0; n < 10 * 5; ++n) {
|
||||||
|
CONDITION_LOCKER(guard, _contextCondition);
|
||||||
|
|
||||||
|
if (_busyContexts.empty()) {
|
||||||
|
LOG_DEBUG("no busy V8 contexts");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
LOG_DEBUG("waiting for %d busy V8 contexts to finish", (int) _busyContexts.size());
|
||||||
|
|
||||||
|
guard.wait(100000);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -753,9 +772,26 @@ void ApplicationV8::close () {
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
void ApplicationV8::stop () {
|
void ApplicationV8::stop () {
|
||||||
// unregister all tasks
|
|
||||||
if (_scheduler != nullptr) {
|
//send all busy contexts a termate signal
|
||||||
_scheduler->scheduler()->unregisterUserTasks();
|
{
|
||||||
|
CONDITION_LOCKER(guard, _contextCondition);
|
||||||
|
|
||||||
|
for (auto it = _busyContexts.begin(); it != _busyContexts.end(); ++it) {
|
||||||
|
LOG_WARNING("sending termination signal to V8 context");
|
||||||
|
v8::V8::TerminateExecution((*it)->_isolate);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// wait for one minute
|
||||||
|
for (size_t n = 0; n < 10 * 60; ++n) {
|
||||||
|
CONDITION_LOCKER(guard, _contextCondition);
|
||||||
|
|
||||||
|
if (_busyContexts.empty()) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
guard.wait(100000);
|
||||||
}
|
}
|
||||||
|
|
||||||
// stop GC
|
// stop GC
|
||||||
|
|
|
@ -114,7 +114,7 @@ static bool SyncDatafile (const TRI_datafile_t* const datafile,
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(datafile->_fd > 0);
|
assert(datafile->_fd >= 0);
|
||||||
|
|
||||||
if (begin == end) {
|
if (begin == end) {
|
||||||
// no need to sync
|
// no need to sync
|
||||||
|
@ -212,7 +212,7 @@ static void InitDatafile (TRI_datafile_t* datafile,
|
||||||
assert(fd == -1);
|
assert(fd == -1);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
assert(fd > 0);
|
assert(fd >= 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
datafile->_state = TRI_DF_STATE_READ;
|
datafile->_state = TRI_DF_STATE_READ;
|
||||||
|
|
|
@ -214,6 +214,16 @@ bool ApplicationDispatcher::open () {
|
||||||
/// {@inheritDoc}
|
/// {@inheritDoc}
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
void ApplicationDispatcher::close () {
|
||||||
|
if (_dispatcher != 0) {
|
||||||
|
_dispatcher->beginShutdown();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// {@inheritDoc}
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
void ApplicationDispatcher::stop () {
|
void ApplicationDispatcher::stop () {
|
||||||
if (_dispatcherReporterTask != 0) {
|
if (_dispatcherReporterTask != 0) {
|
||||||
_dispatcherReporterTask = 0;
|
_dispatcherReporterTask = 0;
|
||||||
|
@ -222,8 +232,6 @@ void ApplicationDispatcher::stop () {
|
||||||
if (_dispatcher != 0) {
|
if (_dispatcher != 0) {
|
||||||
static size_t const MAX_TRIES = 50; // 10 seconds (50 * 200 ms)
|
static size_t const MAX_TRIES = 50; // 10 seconds (50 * 200 ms)
|
||||||
|
|
||||||
_dispatcher->beginShutdown();
|
|
||||||
|
|
||||||
for (size_t count = 0; count < MAX_TRIES && _dispatcher->isRunning(); ++count) {
|
for (size_t count = 0; count < MAX_TRIES && _dispatcher->isRunning(); ++count) {
|
||||||
LOG_TRACE("waiting for dispatcher to stop");
|
LOG_TRACE("waiting for dispatcher to stop");
|
||||||
usleep(200 * 1000);
|
usleep(200 * 1000);
|
||||||
|
|
|
@ -136,6 +136,12 @@ namespace triagens {
|
||||||
|
|
||||||
bool open ();
|
bool open ();
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// {@inheritDoc}
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
void close ();
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
/// {@inheritDoc}
|
/// {@inheritDoc}
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
Loading…
Reference in New Issue