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); cout << TRI_StringifyV8Exception(&tryCatch);
} }
else { else {
// will stop, so need for v8g->_canceled = true;
return EXIT_FAILURE; return EXIT_FAILURE;
} }
} }
@ -1065,6 +1066,7 @@ int ArangoServer::runScript (TRI_vocbase_t* vocbase) {
TRI_LogV8Exception(&tryCatch); TRI_LogV8Exception(&tryCatch);
} }
else { else {
// will stop, so need for v8g->_canceled = true;
return EXIT_FAILURE; 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 // --SECTION-- class ApplicationV8
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
@ -360,10 +379,25 @@ void ApplicationV8::exitContext (V8Context* context) {
// HasOutOfMemoryException must be called while there is still an isolate! // HasOutOfMemoryException must be called while there is still an isolate!
bool const hasOutOfMemoryException = context->_context->HasOutOfMemoryException(); bool const hasOutOfMemoryException = context->_context->HasOutOfMemoryException();
// check for cancelation requests
bool const canceled = v8g->_canceled;
v8g->_canceled = false;
// exit the context // exit the context
context->_context->Exit(); context->_context->Exit();
context->_isolate->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 // try to execute new global context methods
bool runGlobal = false; bool runGlobal = false;
{ {

View File

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

View File

@ -150,7 +150,10 @@ Job::status_t V8Job::work () {
TRI_LogV8Exception(&tryCatch); TRI_LogV8Exception(&tryCatch);
} }
else { 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 { else {
v8g->_canceled = true;
result.isValid = false; result.isValid = false;
result.canceled = true; 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())); return scope.Close(v8::ThrowException(tryCatch.Exception()));
} }
else { 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);
} }
} }
@ -3847,6 +3850,9 @@ static v8::Handle<v8::Value> JS_Transaction (v8::Arguments const& argv) {
return scope.Close(v8::ThrowException(tryCatch.Exception())); return scope.Close(v8::ThrowException(tryCatch.Exception()));
} }
else { 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);
} }
} }
@ -4489,6 +4495,9 @@ static v8::Handle<v8::Value> JS_NextGeneralCursor (v8::Arguments const& argv) {
return scope.Close(v8::ThrowException(tryCatch.Exception())); return scope.Close(v8::ThrowException(tryCatch.Exception()));
} }
else { else {
TRI_v8_global_t* v8g = (TRI_v8_global_t*) v8::Isolate::GetCurrent()->GetData();
v8g->_canceled = true;
return scope.Close(v8::Undefined()); 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())); return scope.Close(v8::ThrowException(tryCatch.Exception()));
} }
else { else {
TRI_v8_global_t* v8g = (TRI_v8_global_t*) v8::Isolate::GetCurrent()->GetData();
v8g->_canceled = true;
return scope.Close(v8::Undefined()); 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()); TRI_ObjectToString(tryCatch.Exception()).c_str());
return scope.Close(v8::ThrowException(errorObject)); 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); 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)); return scope.Close(v8::ThrowException(errorObject));
} }
else { 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);
} }
} }
@ -5636,6 +5657,9 @@ static v8::Handle<v8::Value> JS_ParseAhuacatl (v8::Arguments const& argv) {
return scope.Close(v8::ThrowException(errorObject)); return scope.Close(v8::ThrowException(errorObject));
} }
else { 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);
} }
} }

View File

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

View File

@ -503,74 +503,80 @@ function require (path) {
} }
// create a new module // create a new module
var localModule = currentPackage.defineModule( try {
id, var localModule = currentPackage.defineModule(
"js", id,
new Module(id, currentPackage, currentModule._applicationContext, path, origin, false)); "js",
new Module(id, currentPackage, currentModule._applicationContext, path, origin, false));
// create a new sandbox and execute // create a new sandbox and execute
var env = currentPackage._environment; var env = currentPackage._environment;
var sandbox = {}; var sandbox = {};
sandbox.print = internal.print; sandbox.print = internal.print;
if (env !== undefined) { if (env !== undefined) {
for (key in env) { for (key in env) {
if (env.hasOwnProperty(key) && key !== "__myenv__") { if (env.hasOwnProperty(key) && key !== "__myenv__") {
sandbox[key] = env[key]; sandbox[key] = env[key];
}
} }
} }
}
var filename = fileUri2Path(origin); var filename = fileUri2Path(origin);
if (filename !== null) { if (filename !== null) {
sandbox.__filename = filename; sandbox.__filename = filename;
sandbox.__dirname = normalizeModuleName(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 + "'];";
} }
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;
} }
catch (err) {
script += "delete __myenv__;" currentPackage.clearModule(id, "js");
+ content throw err;
+ "\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;
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
@ -903,6 +909,14 @@ function require (path) {
delete REGISTER_EXECUTE_FILE; delete REGISTER_EXECUTE_FILE;
////////////////////////////////////////////////////////////////////////////////
/// @brief cleans up after cancelation
////////////////////////////////////////////////////////////////////////////////
function cleanupCancelation () {
module.unloadAll();
}
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
// --SECTION-- Package // --SECTION-- Package
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
@ -1106,6 +1120,8 @@ function require (path) {
internal[key] = EXPORTS_SLOW_BUFFER[key]; internal[key] = EXPORTS_SLOW_BUFFER[key];
} }
} }
internal.cleanupCancelation = cleanupCancelation;
}()); }());
delete EXPORTS_SLOW_BUFFER; 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()); return scope.Close(v8::Undefined());
} }
else { else {
TRI_v8_global_t* v8g = static_cast<TRI_v8_global_t*>(v8::Isolate::GetCurrent()->GetData());
v8g->_canceled = true;
return scope.Close(result); return scope.Close(result);
} }
} }
@ -121,6 +124,9 @@ bool JSLoader::loadScript (v8::Persistent<v8::Context> context, string const& na
return false; return false;
} }
else { else {
TRI_v8_global_t* v8g = static_cast<TRI_v8_global_t*>(v8::Isolate::GetCurrent()->GetData());
v8g->_canceled = true;
return false; return false;
} }
} }

View File

@ -74,6 +74,9 @@ TRI_js_exec_context_t* TRI_CreateExecutionContext (char const* script,
ctx->_error = TRI_ERROR_INTERNAL; ctx->_error = TRI_ERROR_INTERNAL;
} }
else { 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; ctx->_error = TRI_ERROR_REQUEST_CANCELED;
} }
return ctx; return ctx;
@ -134,6 +137,9 @@ TRI_json_t* TRI_ExecuteResultContext (TRI_js_exec_context_t* ctx) {
ctx->_error = TRI_ERROR_INTERNAL; ctx->_error = TRI_ERROR_INTERNAL;
} }
else { 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; ctx->_error = TRI_ERROR_REQUEST_CANCELED;
} }
return NULL; return NULL;

View File

@ -128,9 +128,10 @@ TRI_v8_global_s::TRI_v8_global_s (v8::Isolate* isolate)
_resolver(0), _resolver(0),
_server(0), _server(0),
_vocbase(0), _vocbase(0),
_loader(0),
_allowUseDatabase(true), _allowUseDatabase(true),
_hasDeadObjects(false) { _hasDeadObjects(false),
_loader(0),
_canceled(false) {
v8::HandleScope scope; v8::HandleScope scope;
BufferConstant = v8::Persistent<v8::String>::New(isolate, TRI_V8_SYMBOL("Buffer")); 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; void* _vocbase;
////////////////////////////////////////////////////////////////////////////////
/// @brief pointer to the startup loader (JSLoader*)
////////////////////////////////////////////////////////////////////////////////
void* _loader;
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
/// @brief whether or not useDatabase() is allowed /// @brief whether or not useDatabase() is allowed
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
@ -764,6 +758,23 @@ typedef struct TRI_v8_global_s {
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
bool _hasDeadObjects; bool _hasDeadObjects;
// -----------------------------------------------------------------------------
// --SECTION-- GENERAL
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @brief pointer to the startup loader (JSLoader*)
////////////////////////////////////////////////////////////////////////////////
void* _loader;
////////////////////////////////////////////////////////////////////////////////
/// @brief cancel has been caught
////////////////////////////////////////////////////////////////////////////////
bool _canceled;
} }
TRI_v8_global_t; TRI_v8_global_t;

View File

@ -267,6 +267,11 @@ static bool LoadJavaScriptDirectory (char const* path,
if (tryCatch.CanContinue()) { if (tryCatch.CanContinue()) {
TRI_LogV8Exception(&tryCatch); 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()); TRI_V8_SYNTAX_ERROR(scope, err.c_str());
} }
else { else {
TRI_v8_global_t* v8g = static_cast<TRI_v8_global_t*>(v8::Isolate::GetCurrent()->GetData());
v8g->_canceled = true;
return scope.Close(v8::Undefined()); 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())); return scope.Close(v8::ThrowException(tryCatch.Exception()));
} }
else { else {
TRI_v8_global_t* v8g = (TRI_v8_global_t*) v8::Isolate::GetCurrent()->GetData();
v8g->_canceled = true;
return scope.Close(v8::Undefined()); 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())); return scope.Close(v8::ThrowException(tryCatch.Exception()));
} }
else { else {
TRI_v8_global_t* v8g = (TRI_v8_global_t*) v8::Isolate::GetCurrent()->GetData();
v8g->_canceled = true;
return scope.Close(v8::Undefined()); return scope.Close(v8::Undefined());
} }
} }
@ -3300,6 +3314,9 @@ v8::Handle<v8::Value> TRI_ExecuteJavaScriptString (v8::Handle<v8::Context> conte
TRI_LogV8Exception(&tryCatch); TRI_LogV8Exception(&tryCatch);
} }
else { else {
TRI_v8_global_t* v8g = (TRI_v8_global_t*) v8::Isolate::GetCurrent()->GetData();
v8g->_canceled = true;
return scope.Close(v8::Undefined()); return scope.Close(v8::Undefined());
} }
} }