summaryrefslogtreecommitdiff
path: root/src/mongo/dbtests/jstests.cpp
diff options
context:
space:
mode:
authorSpencer Jackson <spencer.jackson@mongodb.com>2018-05-11 17:42:34 -0400
committerSpencer Jackson <spencer.jackson@mongodb.com>2018-05-23 11:10:11 -0400
commitae8f7d8160aef246ea4c31169d42865fc55e98c3 (patch)
tree39a38343ffbd5ee4537beca57aab0cf664f258a1 /src/mongo/dbtests/jstests.cpp
parent4a167b9f823da4ed89735c8846a4348cf085bfb3 (diff)
downloadmongo-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.cpp54
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>();