diff options
author | Spencer Jackson <spencer.jackson@mongodb.com> | 2018-05-11 17:42:34 -0400 |
---|---|---|
committer | Spencer Jackson <spencer.jackson@mongodb.com> | 2018-05-23 11:10:11 -0400 |
commit | ae8f7d8160aef246ea4c31169d42865fc55e98c3 (patch) | |
tree | 39a38343ffbd5ee4537beca57aab0cf664f258a1 /src/mongo/dbtests/jstests.cpp | |
parent | 4a167b9f823da4ed89735c8846a4348cf085bfb3 (diff) | |
download | mongo-ae8f7d8160aef246ea4c31169d42865fc55e98c3.tar.gz |
SERVER-35061: Javascript sleep should error on premature wake
Diffstat (limited to 'src/mongo/dbtests/jstests.cpp')
-rw-r--r-- | src/mongo/dbtests/jstests.cpp | 54 |
1 files changed, 54 insertions, 0 deletions
diff --git a/src/mongo/dbtests/jstests.cpp b/src/mongo/dbtests/jstests.cpp index e928f54b1da..ba43b2802e9 100644 --- a/src/mongo/dbtests/jstests.cpp +++ b/src/mongo/dbtests/jstests.cpp @@ -46,7 +46,9 @@ #include "mongo/scripting/engine.h" #include "mongo/shell/shell_utils.h" #include "mongo/util/concurrency/thread_name.h" +#include "mongo/util/future.h" #include "mongo/util/log.h" +#include "mongo/util/time_support.h" #include "mongo/util/timer.h" using std::cout; @@ -952,6 +954,57 @@ public: } }; +class SleepInterruption { +public: + void run() { + std::shared_ptr<Scope> scope(getGlobalScriptEngine()->newScope()); + + Promise<void> sleepPromise{}; + auto sleepFuture = sleepPromise.getFuture(); + + Promise<void> awakenedPromise{}; + auto awakenedFuture = awakenedPromise.getFuture(); + + // Spawn a thread which attempts to sleep indefinitely. + stdx::thread([ + preSleep = std::move(sleepPromise), + onAwake = std::move(awakenedPromise), + scope + ]() mutable { + preSleep.emplaceValue(); + onAwake.setWith([&] { + scope->exec( + "" + " try {" + " sleep(99999999999);" + " } finally {" + " throw \"FAILURE\";" + " }" + "", + "test", + false, + false, + true); + }); + }).detach(); + + // Wait until just before the sleep begins. + sleepFuture.get(); + + // Attempt to wait until Javascript enters the sleep. + // It's OK if we kill the function prematurely, before it begins sleeping. Either cause of + // death will emit an error with the Interrupted code. + sleepsecs(1); + + // Send the operation a kill signal. + scope->kill(); + + // Wait for the error. + auto result = awakenedFuture.getNoThrow(); + ASSERT_EQ(ErrorCodes::Interrupted, result); + } +}; + /** * Test invoke() timeout value does not terminate execution (SERVER-8053) */ @@ -2547,6 +2600,7 @@ public: add<ExecTimeout>(); add<ExecNoTimeout>(); add<InvokeTimeout>(); + add<SleepInterruption>(); add<InvokeNoTimeout>(); add<ObjectMapping>(); |