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
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
|
/**
* Tests that a backtrace will appear in the $currentOp output if the backtrace option is
* set to true and there is a latch timeout.
*
* The test runs commands that are not allowed with security token: whatsmyuri.
* @tags: [
* not_allowed_with_security_token,
* assumes_read_concern_unchanged,
* assumes_read_preference_unchanged,
* no_selinux
* ]
*/
(function() {
"use strict";
const adminDB = db.getSiblingDB("admin");
// This test causes an extra thread with a self-contended lock to be created so that currentOp can
// observe its DiagnosticInfo. This mutex is test-only, and is at a lower level than the
// SessionCatalog's mutex, so we pass 'idleSessions: false' to avoid scanning idle sessions during
// currentOp and hitting a latch violation.
const getCurrentOp = function() {
jsTestLog("Getting $currentOp");
let result = adminDB
.aggregate(
[
{
$currentOp: {
allUsers: true,
idleConnections: true,
idleSessions: false,
localOps: true,
backtrace: true
}
},
],
{readConcern: {level: "local"}})
.toArray();
assert(result);
return result;
};
const blockedOpClients = {
"DiagnosticCaptureTestLatch": {"seen": false},
"DiagnosticCaptureTestInterruptible": {"seen": false},
};
const getClientName = function() {
let myUri = adminDB.runCommand({whatsmyuri: 1}).you;
return adminDB.aggregate([{$currentOp: {localOps: true}}, {$match: {client: myUri}}])
.toArray()[0]
.desc;
};
let clientName = getClientName();
try {
assert.commandWorked(db.adminCommand({
"configureFailPoint": 'currentOpSpawnsThreadWaitingForLatch',
"mode": 'alwaysOn',
"data": {
'clientName': clientName,
},
}));
const verifyResult = function(result) {
jsTestLog("Verifying " + tojson(result));
assert(result);
assert(result.hasOwnProperty("waitingForLatch"));
assert(result["waitingForLatch"].hasOwnProperty("timestamp"));
assert(result["waitingForLatch"].hasOwnProperty("captureName"));
/* Absent until we have efficient enough backtracing
assert(result["waitingForLatch"].hasOwnProperty("backtrace"));
result["waitingForLatch"]["backtrace"].forEach(function(frame) {
assert(frame.hasOwnProperty("addr"));
assert(typeof frame["addr"] === "string");
assert(frame.hasOwnProperty("path"));
assert(typeof frame["path"] === "string");
});
*/
};
getCurrentOp().forEach(function(op) {
const name = op["desc"];
if (name in blockedOpClients) {
jsTestLog("Verifying " + op["desc"]);
verifyResult(op);
blockedOpClients[name].seen = true;
}
});
// Make sure we saw the ops we expected
for (const name in blockedOpClients) {
assert(blockedOpClients[name].seen);
}
} finally {
assert.commandWorked(db.adminCommand(
{"configureFailPoint": 'currentOpSpawnsThreadWaitingForLatch', "mode": 'off'}));
getCurrentOp().forEach(function(op) {
const name = op["desc"];
if (name in blockedOpClients) {
assert(!op.hasOwnProperty("waitingForLatch"));
}
});
}
})();
|