diff --git a/arangod/RestServer/ArangoServer.cpp b/arangod/RestServer/ArangoServer.cpp index 2414809321..d8f3019699 100644 --- a/arangod/RestServer/ArangoServer.cpp +++ b/arangod/RestServer/ArangoServer.cpp @@ -761,6 +761,7 @@ void ArangoServer::buildApplicationServer () { //////////////////////////////////////////////////////////////////////////////// int ArangoServer::startupServer () { + OperationMode::server_operation_mode_e mode = OperationMode::determineMode(_applicationServer->programOptions()); // ............................................................................. // prepare the various parts of the Arango server @@ -783,8 +784,21 @@ int ArangoServer::startupServer () { assert(vocbase != 0); // 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->setConcurrency(_dispatcherThreads); + _applicationV8->setConcurrency(concurrency); if (_applicationServer->programOptions().has("upgrade")) { _applicationV8->performUpgrade(); @@ -855,8 +869,6 @@ int ArangoServer::startupServer () { 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; if (mode == OperationMode::MODE_CONSOLE) { diff --git a/arangod/RestServer/ConsoleThread.cpp b/arangod/RestServer/ConsoleThread.cpp index 39af6ad6da..453ff464b1 100644 --- a/arangod/RestServer/ConsoleThread.cpp +++ b/arangod/RestServer/ConsoleThread.cpp @@ -90,19 +90,20 @@ void ConsoleThread::run () { try { inner(); - _applicationV8->exitContext(_context); - _done = 1; } catch (const char*) { - _applicationV8->exitContext(_context); - _done = 1; } catch (...) { _applicationV8->exitContext(_context); _done = 1; + _applicationServer->beginShutdown(); throw; } + + _applicationV8->exitContext(_context); + _done = 1; + _applicationServer->beginShutdown(); } // ----------------------------------------------------------------------------- @@ -156,7 +157,6 @@ void ConsoleThread::inner () { if (input == 0) { _userAborted = true; - _applicationServer->beginShutdown(); // this will be caught by "run" throw "user aborted"; diff --git a/arangod/RestServer/ConsoleThread.h b/arangod/RestServer/ConsoleThread.h index 4cfe8bce1c..1e20b832de 100644 --- a/arangod/RestServer/ConsoleThread.h +++ b/arangod/RestServer/ConsoleThread.h @@ -96,7 +96,6 @@ namespace triagens { void userAbort () { _userAborted = true; - TRI_CLOSE(0); } //////////////////////////////////////////////////////////////////////////////// diff --git a/arangod/V8Server/ApplicationV8.cpp b/arangod/V8Server/ApplicationV8.cpp index 477ca7d34d..d6a9327b3b 100644 --- a/arangod/V8Server/ApplicationV8.cpp +++ b/arangod/V8Server/ApplicationV8.cpp @@ -746,6 +746,25 @@ bool ApplicationV8::start () { void ApplicationV8::close () { _stopping = 1; _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 () { - // unregister all tasks - if (_scheduler != nullptr) { - _scheduler->scheduler()->unregisterUserTasks(); + + //send all busy contexts a termate signal + { + 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 diff --git a/arangod/VocBase/datafile.cpp b/arangod/VocBase/datafile.cpp index 3fda1abbcb..59bbc1c088 100644 --- a/arangod/VocBase/datafile.cpp +++ b/arangod/VocBase/datafile.cpp @@ -114,7 +114,7 @@ static bool SyncDatafile (const TRI_datafile_t* const datafile, return true; } - assert(datafile->_fd > 0); + assert(datafile->_fd >= 0); if (begin == end) { // no need to sync @@ -212,7 +212,7 @@ static void InitDatafile (TRI_datafile_t* datafile, assert(fd == -1); } else { - assert(fd > 0); + assert(fd >= 0); } datafile->_state = TRI_DF_STATE_READ; diff --git a/lib/Dispatcher/ApplicationDispatcher.cpp b/lib/Dispatcher/ApplicationDispatcher.cpp index 416f8e9369..5f695b9de8 100644 --- a/lib/Dispatcher/ApplicationDispatcher.cpp +++ b/lib/Dispatcher/ApplicationDispatcher.cpp @@ -214,6 +214,16 @@ bool ApplicationDispatcher::open () { /// {@inheritDoc} //////////////////////////////////////////////////////////////////////////////// +void ApplicationDispatcher::close () { + if (_dispatcher != 0) { + _dispatcher->beginShutdown(); + } +} + +//////////////////////////////////////////////////////////////////////////////// +/// {@inheritDoc} +//////////////////////////////////////////////////////////////////////////////// + void ApplicationDispatcher::stop () { if (_dispatcherReporterTask != 0) { _dispatcherReporterTask = 0; @@ -222,8 +232,6 @@ void ApplicationDispatcher::stop () { if (_dispatcher != 0) { 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) { LOG_TRACE("waiting for dispatcher to stop"); usleep(200 * 1000); diff --git a/lib/Dispatcher/ApplicationDispatcher.h b/lib/Dispatcher/ApplicationDispatcher.h index f6b0a8b532..84c30fe561 100644 --- a/lib/Dispatcher/ApplicationDispatcher.h +++ b/lib/Dispatcher/ApplicationDispatcher.h @@ -136,6 +136,12 @@ namespace triagens { bool open (); +//////////////////////////////////////////////////////////////////////////////// +/// {@inheritDoc} +//////////////////////////////////////////////////////////////////////////////// + + void close (); + //////////////////////////////////////////////////////////////////////////////// /// {@inheritDoc} ////////////////////////////////////////////////////////////////////////////////