1
0
Fork 0

if a cancelation has occured, flush the module cache

This commit is contained in:
Frank Celler 2014-07-08 11:54:42 +02:00
parent c2fa9cb091
commit e436ecfa40
13 changed files with 197 additions and 70 deletions

View File

@ -1001,6 +1001,7 @@ int ArangoServer::runUnitTests (TRI_vocbase_t* vocbase) {
cout << TRI_StringifyV8Exception(&tryCatch);
}
else {
// will stop, so need for v8g->_canceled = true;
return EXIT_FAILURE;
}
}
@ -1065,6 +1066,7 @@ int ArangoServer::runScript (TRI_vocbase_t* vocbase) {
TRI_LogV8Exception(&tryCatch);
}
else {
// will stop, so need for v8g->_canceled = true;
return EXIT_FAILURE;
}
}

View File

@ -148,7 +148,11 @@ namespace {
}
// -----------------------------------------------------------------------------
// --SECTION-- public types
// --SECTION-- class V8Context
// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
// --SECTION-- public methods
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
@ -208,6 +212,21 @@ void ApplicationV8::V8Context::handleGlobalContextMethods () {
}
}
////////////////////////////////////////////////////////////////////////////////
/// @brief executes the cancelation cleanup
////////////////////////////////////////////////////////////////////////////////
void ApplicationV8::V8Context::handleCancelationCleanup () {
v8::HandleScope scope;
LOG_DEBUG("executing cancelation cleanup context %d", (int) _id);
TRI_ExecuteJavaScriptString(_context,
v8::String::New("require('internal').cleanupCancelation();"),
v8::String::New("context cleanup method"),
false);
}
// -----------------------------------------------------------------------------
// --SECTION-- class ApplicationV8
// -----------------------------------------------------------------------------
@ -360,10 +379,25 @@ void ApplicationV8::exitContext (V8Context* context) {
// HasOutOfMemoryException must be called while there is still an isolate!
bool const hasOutOfMemoryException = context->_context->HasOutOfMemoryException();
// check for cancelation requests
bool const canceled = v8g->_canceled;
v8g->_canceled = false;
// exit the context
context->_context->Exit();
context->_isolate->Exit();
// if the execution was canceled, we need to cleanup
if (canceled) {
context->_isolate->Enter();
context->_context->Enter();
context->handleCancelationCleanup();
context->_context->Exit();
context->_isolate->Exit();
}
// try to execute new global context methods
bool runGlobal = false;
{

View File

@ -188,6 +188,12 @@ namespace triagens {
void handleGlobalContextMethods ();
////////////////////////////////////////////////////////////////////////////////
/// @brief executes the cancelation cleanup
////////////////////////////////////////////////////////////////////////////////
void handleCancelationCleanup ();
////////////////////////////////////////////////////////////////////////////////
/// @brief mutex to protect _globalMethods
////////////////////////////////////////////////////////////////////////////////

View File

@ -150,7 +150,10 @@ Job::status_t V8Job::work () {
TRI_LogV8Exception(&tryCatch);
}
else {
LOG_WARNING("caught non-printable exception in periodic task");
TRI_v8_global_t* v8g = (TRI_v8_global_t*) v8::Isolate::GetCurrent()->GetData();
v8g->_canceled = true;
LOG_WARNING("caught non-catchable exception (aka termination) in periodic job");
}
}
}

View File

@ -730,6 +730,7 @@ static TRI_action_result_t ExecuteActionVocbase (TRI_vocbase_t* vocbase,
}
}
else {
v8g->_canceled = true;
result.isValid = false;
result.canceled = true;
}

View File

@ -3499,6 +3499,9 @@ static v8::Handle<v8::Value> ExecuteQueryCursorAhuacatl (TRI_vocbase_t* const vo
return scope.Close(v8::ThrowException(tryCatch.Exception()));
}
else {
TRI_v8_global_t* v8g = (TRI_v8_global_t*) v8::Isolate::GetCurrent()->GetData();
v8g->_canceled = true;
return scope.Close(result);
}
}
@ -3847,6 +3850,9 @@ static v8::Handle<v8::Value> JS_Transaction (v8::Arguments const& argv) {
return scope.Close(v8::ThrowException(tryCatch.Exception()));
}
else {
TRI_v8_global_t* v8g = (TRI_v8_global_t*) v8::Isolate::GetCurrent()->GetData();
v8g->_canceled = true;
return scope.Close(result);
}
}
@ -4489,6 +4495,9 @@ static v8::Handle<v8::Value> JS_NextGeneralCursor (v8::Arguments const& argv) {
return scope.Close(v8::ThrowException(tryCatch.Exception()));
}
else {
TRI_v8_global_t* v8g = (TRI_v8_global_t*) v8::Isolate::GetCurrent()->GetData();
v8g->_canceled = true;
return scope.Close(v8::Undefined());
}
}
@ -4566,6 +4575,9 @@ static v8::Handle<v8::Value> JS_ToArrayGeneralCursor (v8::Arguments const& argv)
return scope.Close(v8::ThrowException(tryCatch.Exception()));
}
else {
TRI_v8_global_t* v8g = (TRI_v8_global_t*) v8::Isolate::GetCurrent()->GetData();
v8g->_canceled = true;
return scope.Close(v8::Undefined());
}
}
@ -5433,6 +5445,12 @@ static v8::Handle<v8::Value> JS_RunAhuacatl (v8::Arguments const& argv) {
TRI_ObjectToString(tryCatch.Exception()).c_str());
return scope.Close(v8::ThrowException(errorObject));
}
else {
TRI_v8_global_t* v8g = (TRI_v8_global_t*) v8::Isolate::GetCurrent()->GetData();
v8g->_canceled = true;
return scope.Close(result);
}
}
return scope.Close(result);
@ -5562,6 +5580,9 @@ static v8::Handle<v8::Value> JS_ExplainAhuacatl (v8::Arguments const& argv) {
return scope.Close(v8::ThrowException(errorObject));
}
else {
TRI_v8_global_t* v8g = (TRI_v8_global_t*) v8::Isolate::GetCurrent()->GetData();
v8g->_canceled = true;
return scope.Close(result);
}
}
@ -5636,6 +5657,9 @@ static v8::Handle<v8::Value> JS_ParseAhuacatl (v8::Arguments const& argv) {
return scope.Close(v8::ThrowException(errorObject));
}
else {
TRI_v8_global_t* v8g = (TRI_v8_global_t*) v8::Isolate::GetCurrent()->GetData();
v8g->_canceled = true;
return scope.Close(result);
}
}

View File

@ -2238,7 +2238,7 @@ var checkIfMayBeDropped = function(colName, graphName, graphs) {
return;
}
var edgeDefinitions = graph.edgeDefinitions;
if (graph.edgeDefinitions) {
if (edgeDefinitions) {
edgeDefinitions.forEach(
function(edgeDefinition) {
var from = edgeDefinition.from;
@ -2257,7 +2257,7 @@ var checkIfMayBeDropped = function(colName, graphName, graphs) {
var orphanCollections = graph.orphanCollections;
if (orphanCollections) {
if (orphanCollections.indexOf(colName) !== -1) {
return false;
result = false;
}
}
}

View File

@ -503,74 +503,80 @@ function require (path) {
}
// create a new module
var localModule = currentPackage.defineModule(
id,
"js",
new Module(id, currentPackage, currentModule._applicationContext, path, origin, false));
try {
var localModule = currentPackage.defineModule(
id,
"js",
new Module(id, currentPackage, currentModule._applicationContext, path, origin, false));
// create a new sandbox and execute
var env = currentPackage._environment;
// create a new sandbox and execute
var env = currentPackage._environment;
var sandbox = {};
sandbox.print = internal.print;
var sandbox = {};
sandbox.print = internal.print;
if (env !== undefined) {
for (key in env) {
if (env.hasOwnProperty(key) && key !== "__myenv__") {
sandbox[key] = env[key];
if (env !== undefined) {
for (key in env) {
if (env.hasOwnProperty(key) && key !== "__myenv__") {
sandbox[key] = env[key];
}
}
}
}
var filename = fileUri2Path(origin);
var filename = fileUri2Path(origin);
if (filename !== null) {
sandbox.__filename = filename;
sandbox.__dirname = normalizeModuleName(filename + "/..");
}
sandbox.module = localModule;
sandbox.exports = localModule.exports;
sandbox.require = function(path) {
return localModule.require(path);
};
if (localModule.hasOwnProperty("_applicationContext")) {
sandbox.applicationContext = localModule._applicationContext;
}
// try to execute the module source code
var script = "(function (__myenv__) {";
for (key in sandbox) {
if (sandbox.hasOwnProperty(key)) {
script += "var " + key + " = __myenv__['" + key + "'];";
if (filename !== null) {
sandbox.__filename = filename;
sandbox.__dirname = normalizeModuleName(filename + "/..");
}
sandbox.module = localModule;
sandbox.exports = localModule.exports;
sandbox.require = function(path) {
return localModule.require(path);
};
if (localModule.hasOwnProperty("_applicationContext")) {
sandbox.applicationContext = localModule._applicationContext;
}
// try to execute the module source code
var script = "(function (__myenv__) {";
for (key in sandbox) {
if (sandbox.hasOwnProperty(key)) {
script += "var " + key + " = __myenv__['" + key + "'];";
}
}
script += "delete __myenv__;"
+ content
+ "\n});";
var fun = internal.executeScript(script, undefined, filename);
if (fun === undefined) {
e = new Error("corrupted package '" + path
+ "', cannot create module context function for: "
+ script);
e.moduleNotFound = false;
e._path = path;
e._package = currentPackage.id;
e._packageOrigin = currentPackage._origin;
throw e;
}
fun(sandbox);
return localModule;
}
script += "delete __myenv__;"
+ content
+ "\n});";
var fun = internal.executeScript(script, undefined, filename);
if (fun === undefined) {
e = new Error("corrupted package '" + path
+ "', cannot create module context function for: "
+ script);
e.moduleNotFound = false;
e._path = path;
e._package = currentPackage.id;
e._packageOrigin = currentPackage._origin;
throw e;
catch (err) {
currentPackage.clearModule(id, "js");
throw err;
}
fun(sandbox);
return localModule;
}
////////////////////////////////////////////////////////////////////////////////
@ -903,6 +909,14 @@ function require (path) {
delete REGISTER_EXECUTE_FILE;
////////////////////////////////////////////////////////////////////////////////
/// @brief cleans up after cancelation
////////////////////////////////////////////////////////////////////////////////
function cleanupCancelation () {
module.unloadAll();
}
// -----------------------------------------------------------------------------
// --SECTION-- Package
// -----------------------------------------------------------------------------
@ -1106,6 +1120,8 @@ function require (path) {
internal[key] = EXPORTS_SLOW_BUFFER[key];
}
}
internal.cleanupCancelation = cleanupCancelation;
}());
delete EXPORTS_SLOW_BUFFER;

View File

@ -85,6 +85,9 @@ v8::Handle<v8::Value> JSLoader::executeGlobalScript (v8::Handle<v8::Context> con
return scope.Close(v8::Undefined());
}
else {
TRI_v8_global_t* v8g = static_cast<TRI_v8_global_t*>(v8::Isolate::GetCurrent()->GetData());
v8g->_canceled = true;
return scope.Close(result);
}
}
@ -121,6 +124,9 @@ bool JSLoader::loadScript (v8::Persistent<v8::Context> context, string const& na
return false;
}
else {
TRI_v8_global_t* v8g = static_cast<TRI_v8_global_t*>(v8::Isolate::GetCurrent()->GetData());
v8g->_canceled = true;
return false;
}
}

View File

@ -74,6 +74,9 @@ TRI_js_exec_context_t* TRI_CreateExecutionContext (char const* script,
ctx->_error = TRI_ERROR_INTERNAL;
}
else {
TRI_v8_global_t* v8g = static_cast<TRI_v8_global_t*>(v8::Isolate::GetCurrent()->GetData());
v8g->_canceled = true;
ctx->_error = TRI_ERROR_REQUEST_CANCELED;
}
return ctx;
@ -134,6 +137,9 @@ TRI_json_t* TRI_ExecuteResultContext (TRI_js_exec_context_t* ctx) {
ctx->_error = TRI_ERROR_INTERNAL;
}
else {
TRI_v8_global_t* v8g = static_cast<TRI_v8_global_t*>(v8::Isolate::GetCurrent()->GetData());
v8g->_canceled = true;
ctx->_error = TRI_ERROR_REQUEST_CANCELED;
}
return NULL;

View File

@ -128,9 +128,10 @@ TRI_v8_global_s::TRI_v8_global_s (v8::Isolate* isolate)
_resolver(0),
_server(0),
_vocbase(0),
_loader(0),
_allowUseDatabase(true),
_hasDeadObjects(false) {
_hasDeadObjects(false),
_loader(0),
_canceled(false) {
v8::HandleScope scope;
BufferConstant = v8::Persistent<v8::String>::New(isolate, TRI_V8_SYMBOL("Buffer"));

View File

@ -746,12 +746,6 @@ typedef struct TRI_v8_global_s {
void* _vocbase;
////////////////////////////////////////////////////////////////////////////////
/// @brief pointer to the startup loader (JSLoader*)
////////////////////////////////////////////////////////////////////////////////
void* _loader;
////////////////////////////////////////////////////////////////////////////////
/// @brief whether or not useDatabase() is allowed
////////////////////////////////////////////////////////////////////////////////
@ -764,6 +758,23 @@ typedef struct TRI_v8_global_s {
////////////////////////////////////////////////////////////////////////////////
bool _hasDeadObjects;
// -----------------------------------------------------------------------------
// --SECTION-- GENERAL
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @brief pointer to the startup loader (JSLoader*)
////////////////////////////////////////////////////////////////////////////////
void* _loader;
////////////////////////////////////////////////////////////////////////////////
/// @brief cancel has been caught
////////////////////////////////////////////////////////////////////////////////
bool _canceled;
}
TRI_v8_global_t;

View File

@ -267,6 +267,11 @@ static bool LoadJavaScriptDirectory (char const* path,
if (tryCatch.CanContinue()) {
TRI_LogV8Exception(&tryCatch);
}
else {
TRI_v8_global_t* v8g = static_cast<TRI_v8_global_t*>(v8::Isolate::GetCurrent()->GetData());
v8g->_canceled = true;
}
}
}
@ -418,6 +423,9 @@ static v8::Handle<v8::Value> JS_Parse (v8::Arguments const& argv) {
TRI_V8_SYNTAX_ERROR(scope, err.c_str());
}
else {
TRI_v8_global_t* v8g = static_cast<TRI_v8_global_t*>(v8::Isolate::GetCurrent()->GetData());
v8g->_canceled = true;
return scope.Close(v8::Undefined());
}
}
@ -828,6 +836,9 @@ static v8::Handle<v8::Value> JS_Execute (v8::Arguments const& argv) {
return scope.Close(v8::ThrowException(tryCatch.Exception()));
}
else {
TRI_v8_global_t* v8g = (TRI_v8_global_t*) v8::Isolate::GetCurrent()->GetData();
v8g->_canceled = true;
return scope.Close(v8::Undefined());
}
}
@ -846,6 +857,9 @@ static v8::Handle<v8::Value> JS_Execute (v8::Arguments const& argv) {
return scope.Close(v8::ThrowException(tryCatch.Exception()));
}
else {
TRI_v8_global_t* v8g = (TRI_v8_global_t*) v8::Isolate::GetCurrent()->GetData();
v8g->_canceled = true;
return scope.Close(v8::Undefined());
}
}
@ -3300,6 +3314,9 @@ v8::Handle<v8::Value> TRI_ExecuteJavaScriptString (v8::Handle<v8::Context> conte
TRI_LogV8Exception(&tryCatch);
}
else {
TRI_v8_global_t* v8g = (TRI_v8_global_t*) v8::Isolate::GetCurrent()->GetData();
v8g->_canceled = true;
return scope.Close(v8::Undefined());
}
}