Skip to content
This repository was archived by the owner on Apr 22, 2023. It is now read-only.

Commit 648f536

Browse files
committed
Fix issue with unexited contexts in vm module
This EvalMachine function is an RIAA nightmare and doesn't enter and exit contexts correctly. I used an auto_ptr with a Context::Scope to handle the dynamic nature of EvalMachine's behavior and created a class which will dispose a persitent handle at the end of scope. This ensures 100% that the context is exited if needed, and disposed if needed.
1 parent aac31bc commit 648f536

1 file changed

Lines changed: 21 additions & 18 deletions

File tree

src/node_script.cc

Lines changed: 21 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
#include "node.h"
2323
#include "node_script.h"
2424
#include <assert.h>
25+
#include <memory>
2526

2627
namespace node {
2728

@@ -98,6 +99,18 @@ class WrappedScript : ObjectWrap {
9899
Persistent<Script> script_;
99100
};
100101

102+
template <class T> class PersistentScope {
103+
public:
104+
explicit inline PersistentScope(Persistent<T> handle) : handle_(handle) {}
105+
inline ~PersistentScope() {
106+
if (!handle_.IsEmpty()) {
107+
handle_.Dispose();
108+
}
109+
}
110+
private:
111+
Persistent<T> handle_;
112+
};
113+
101114

102115
Persistent<Function> cloneObjectMethod;
103116

@@ -358,13 +371,18 @@ Handle<Value> WrappedScript::EvalMachine(const Arguments& args) {
358371
} else if (context_flag == userContext) {
359372
// Use the passed in context
360373
WrappedContext *nContext = ObjectWrap::Unwrap<WrappedContext>(sandbox);
361-
context = nContext->GetV8Context();
374+
context = Persistent<Context>::New(nContext->GetV8Context());
362375
}
363376

377+
// context_scope will enter and exit the Context automatically
378+
std::auto_ptr<Context::Scope> context_scope;
379+
// context_dtor will dispose the persistent handle automatically
380+
PersistentScope<Context> context_dtor(context);
381+
364382
// New and user context share code. DRY it up.
365383
if (context_flag == userContext || context_flag == newContext) {
366-
// Enter the context
367-
context->Enter();
384+
// Enter the context. Disposes it at the end of this function. Magic.
385+
context_scope.reset(new Context::Scope(context));
368386

369387
// Copy everything from the passed in sandbox (either the persistent
370388
// context for runInContext(), or the sandbox arg to runInNewContext()).
@@ -407,11 +425,6 @@ Handle<Value> WrappedScript::EvalMachine(const Arguments& args) {
407425
if (output_flag == returnResult) {
408426
result = script->Run();
409427
if (result.IsEmpty()) {
410-
if (context_flag == newContext) {
411-
context->DetachGlobal();
412-
context->Exit();
413-
context.Dispose();
414-
}
415428
return try_catch.ReThrow();
416429
}
417430
} else {
@@ -429,16 +442,6 @@ Handle<Value> WrappedScript::EvalMachine(const Arguments& args) {
429442
CloneObject(args.This(), context->Global()->GetPrototype(), sandbox);
430443
}
431444

432-
if (context_flag == newContext) {
433-
// Clean up, clean up, everybody everywhere!
434-
context->DetachGlobal();
435-
context->Exit();
436-
context.Dispose();
437-
} else if (context_flag == userContext) {
438-
// Exit the passed in context.
439-
context->Exit();
440-
}
441-
442445
return result == args.This() ? result : scope.Close(result);
443446
}
444447

0 commit comments

Comments
 (0)