1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
|
/**
* Basic test of killop functionality.
*
* Theory of operation: Creates two operations that will take a long time, sends killop for those
* operations, and then attempts to infer that the operations died because of killop, and not for
* some other reason.
*
* NOTES:
* The long operations are count({$where: function () { while (1) ; } }). These operations do not
* terminate until the server determines that they've spent too much time in JS execution, typically
* after 30 seconds of wall clock time have passed. For these operations to take a long time, the
* counted collection must not be empty; hence an initial write to the collection is required.
*/
t = db.jstests_killop;
t.drop();
t.save( {x:1} );
/**
* This function filters for the operations that we're looking for, based on their state and
* the contents of their query object.
*/
function ops() {
p = db.currentOp().inprog;
ids = [];
for ( var i in p ) {
var o = p[ i ];
// We *can't* check for ns, b/c it's not guaranteed to be there unless the query is active, which
// it may not be in our polling cycle - particularly b/c we sleep every second in both the query and
// the assert
if ( ( o.active || o.waitingForLock ) && o.query && o.query.query && o.query.query.$where && o.query.count == "jstests_killop" ) {
ids.push( o.opid );
}
}
return ids;
}
jsTestLog("Starting long-running $where operation");
var s1 = startParallelShell(
"db.jstests_killop.count( { $where: function() { while( 1 ) { ; } } } )" );
var s2 = startParallelShell(
"db.jstests_killop.count( { $where: function() { while( 1 ) { ; } } } )" );
jsTestLog("Finding ops in currentOp() output");
o = [];
assert.soon(function() { o = ops(); return o.length == 2; },
{ toString: function () { return tojson(db.currentOp().inprog); } },
10000);
start = new Date();
jsTestLog("Killing ops");
db.killOp( o[ 0 ] );
db.killOp( o[ 1 ] );
jsTestLog("Waiting for ops to terminate");
[s1, s2].forEach(function(awaitShell) {
var exitCode = awaitShell({checkExitSuccess: false});
assert.neq(0, exitCode,
"expected shell to exit abnormally due to JS execution being terminated");
});
// don't want to pass if timeout killed the js function.
var end = new Date();
var diff = end - start;
assert.lt( diff, 30000, "Start: " + start + "; end: " + end + "; diff: " + diff);
|