diff options
author | Ian Boros <ian.boros@mongodb.com> | 2019-10-01 20:47:51 +0000 |
---|---|---|
committer | evergreen <evergreen@mongodb.com> | 2019-10-01 20:47:51 +0000 |
commit | e77b9df00d5a269c8eb4955efef2c21c42819306 (patch) | |
tree | 27a6d394151b0fb72fe34f18a6263629f0e5c424 /jstests/noPassthroughWithMongod | |
parent | 6a0a923c9ddd7dfe83dfc0ae12fbfb0e7665bfbc (diff) | |
download | mongo-e77b9df00d5a269c8eb4955efef2c21c42819306.tar.gz |
SERVER-43202 propagate errors from interrupts during yielding
Diffstat (limited to 'jstests/noPassthroughWithMongod')
-rw-r--r-- | jstests/noPassthroughWithMongod/interrupt_while_yielded.js | 111 |
1 files changed, 111 insertions, 0 deletions
diff --git a/jstests/noPassthroughWithMongod/interrupt_while_yielded.js b/jstests/noPassthroughWithMongod/interrupt_while_yielded.js new file mode 100644 index 00000000000..935e5224ea9 --- /dev/null +++ b/jstests/noPassthroughWithMongod/interrupt_while_yielded.js @@ -0,0 +1,111 @@ +(function() { +"use strict"; + +const kFailPointName = "setYieldAllLocksHang"; +const kCommandComment = "interruptedWhileYieldedComment"; + +const coll = db.interrupt_while_yielded; +coll.drop(); +assert.commandWorked(coll.insert({a: 1, b: 1, c: 1})); +assert.commandWorked(coll.insert({a: 1, b: 1, c: 1})); + +assert.commandWorked(coll.createIndex({a: 1, b: 1})); +assert.commandWorked(coll.createIndex({a: 1, c: 1})); + +// This is needed to make sure that a yield point is reached. +assert.commandWorked(db.adminCommand({setParameter: 1, internalQueryExecYieldIterations: 1})); + +function runTestWithQuery(queryFn) { + let waitForParallelShell = null; + + try { + assert.commandWorked(db.adminCommand({ + configureFailPoint: kFailPointName, + mode: "alwaysOn", + data: {namespace: coll.getFullName(), checkForInterruptAfterHang: true} + })); + + // Run a command that should hit the fail point in a parallel shell. + let code = `let queryFn = ${queryFn};`; + code += `const coll = db.${coll.getName()};`; + code += `const kCommandComment = "${kCommandComment}";`; + function parallelShellFn() { + const err = assert.throws(queryFn); + assert.commandFailedWithCode(err, [ErrorCodes.Interrupted]); + } + code += "(" + parallelShellFn.toString() + ")();"; + + waitForParallelShell = startParallelShell(code); + + // Find the operation running the query. + let opId = null; + + assert.soon(function() { + const ops = db.getSiblingDB("admin") + .aggregate([ + {$currentOp: {allUsers: true, localOps: true}}, + { + $match: { + numYields: {$gt: 0}, + ns: coll.getFullName(), + "command.comment": kCommandComment + } + } + ]) + .toArray(); + + if (ops.length > 0) { + assert.eq(ops.length, 1); + opId = ops[0].opid; + return true; + } + + return false; + }); + + // Kill the op. + db.killOp(opId); + + } finally { + // Disable the failpoint so that the server will continue, and hit an interrupt check. + assert.commandWorked(db.adminCommand({configureFailPoint: kFailPointName, mode: "off"})); + + if (waitForParallelShell) { + waitForParallelShell(); + } + } + + // Check that the server is still up. + assert.commandWorked(db.adminCommand({isMaster: 1})); +} + +function rootedOr() { + coll.find({$or: [{a: 1}, {b: 1}]}).comment(kCommandComment).itcount(); +} +runTestWithQuery(rootedOr); + +function groupFindDistinct() { + coll.aggregate([{$group: {_id: "$a"}}], {comment: kCommandComment}).itcount(); +} +runTestWithQuery(groupFindDistinct); + +function projectImmediatelyAfterMatch() { + coll.aggregate([{$match: {a: 1}}, {$project: {_id: 0, a: 1}}, {$unwind: "$a"}], + {comment: kCommandComment}) + .itcount(); +} +runTestWithQuery(projectImmediatelyAfterMatch); + +function sortImmediatelyAfterMatch() { + coll.aggregate([{$match: {a: 1, b: 1, c: 1}}, {$sort: {a: 1}}], {comment: kCommandComment}) + .itcount(); +} +runTestWithQuery(sortImmediatelyAfterMatch); + +function sortAndProjectionImmediatelyAfterMatch() { + coll.aggregate([{$match: {a: 1}}, {$project: {_id: 0, a: 1}}, {$sort: {a: 1}}], + {comment: kCommandComment}) + .itcount(); +} +runTestWithQuery(sortAndProjectionImmediatelyAfterMatch); +}()); |