Add support for manually triggered OOM
Suggested-by: Mikko Rantalainen <mikko.rantalainen@gmail.com>
This commit is contained in:
parent
7af0c1d7e8
commit
8ed7678a74
@ -23,6 +23,9 @@
|
||||
.js-text--default-show {
|
||||
/* empty just used to show elements in the default view */
|
||||
}
|
||||
.js-text--display-none {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.table__sub-section--bold {
|
||||
font-weight: bold;
|
||||
@ -59,6 +62,13 @@
|
||||
max-height: 200px;
|
||||
}
|
||||
|
||||
.js-oom-automatic--show {
|
||||
/* empty - used to show sections for automatically triggered OOMs */
|
||||
}
|
||||
.js-oom-manual--show {
|
||||
/* empty - used to show sections for manually triggered OOMs */
|
||||
}
|
||||
|
||||
.result__table {
|
||||
border-collapse: collapse;
|
||||
padding: 10px;
|
||||
@ -149,9 +159,6 @@
|
||||
color: #D8000C;
|
||||
background-color: #FFD2D2;
|
||||
}
|
||||
.js-text--display-none {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.license__text {
|
||||
font-size: small;
|
||||
@ -282,16 +289,28 @@ window.onerror = function (msg, url, lineNo, columnNo, error) {
|
||||
|
||||
<h3>Summary</h3>
|
||||
<div id="explanation">
|
||||
<p>
|
||||
The system couldn't satisfy this request and started the OOM killer to free memory. The OOM killer
|
||||
calculates a score for each process and terminates the process with the highest score to satisfy the
|
||||
initial memory request.
|
||||
</p>
|
||||
<p>
|
||||
The process "<span class="trigger_proc_name"></span>" (PID <span class="trigger_proc_pid"></span>)
|
||||
requested <span class="trigger_proc_requested_memory_pages_kb"></span>
|
||||
(<span class="trigger_proc_requested_memory_pages"></span>) memory.
|
||||
</p>
|
||||
<div class="js-text--default-show js-oom-automatic--show">
|
||||
<p>
|
||||
The OOM killer was automatically triggered to free memory, because the system couldn't satisfy the
|
||||
memory request.
|
||||
The OOM killer calculates a score for each process and terminates the process with the highest score
|
||||
to satisfy the original memory request.
|
||||
</p>
|
||||
<p>
|
||||
The process "<span class="trigger_proc_name"></span>" (PID <span
|
||||
class="trigger_proc_pid"></span>)
|
||||
requested <span class="trigger_proc_requested_memory_pages_kb"></span>
|
||||
(<span class="trigger_proc_requested_memory_pages"></span>) memory.
|
||||
</p>
|
||||
</div>
|
||||
<div class="js-text--default-show js-oom-manual--show">
|
||||
<p>
|
||||
The OOM killer was manually triggered (e.g. with "<code>echo f > /proc/sysrq-trigger</code>")
|
||||
by a user with root privileges.
|
||||
There is no demand to free memory but the OOM killer started nevertheless.
|
||||
The OOM killer calculates a score for each process and terminates the process with the highest score.
|
||||
</p>
|
||||
</div>
|
||||
<p>
|
||||
The process "<span class="killed_proc_name"></span>"
|
||||
(PID <span class="killed_proc_pid"></span>) with an OOM score of <span class="killed_proc_score"></span>
|
||||
@ -326,7 +345,7 @@ window.onerror = function (msg, url, lineNo, columnNo, error) {
|
||||
<tr>
|
||||
<th colspan="3" scope="row">Trigger Process</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<tr class="js-oom-automatic--show">
|
||||
<td></td>
|
||||
<td class="text--align-right"><span class="trigger_proc_name"></span> (PID <span class="trigger_proc_pid"></span>)</td>
|
||||
<td>This process requests memory and is triggering thereby the OOM situation.</td>
|
||||
@ -342,7 +361,7 @@ window.onerror = function (msg, url, lineNo, columnNo, error) {
|
||||
<td class="trigger_proc_nodemask text--align-right"></td>
|
||||
<td>Bit mask indicating the cores on which the process can run.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<tr class="js-oom-automatic--show">
|
||||
<td>Requested memory<br>(order)</td>
|
||||
<td class="text--align-right">
|
||||
<span class="trigger_proc_requested_memory_pages"></span> (2<span class="trigger_proc_order text__superscript"></span>) pages /
|
||||
@ -842,6 +861,7 @@ window.onerror = function (msg, url, lineNo, columnNo, error) {
|
||||
<li>Fix to allow process names with spaces</li>
|
||||
<li>Rework removal of unused information</li>
|
||||
<li>Report uncaught errors to the user</li>
|
||||
<li>Add support for manually triggered OOM (suggested by Mikko Rantalainen)</li>
|
||||
<li>...</li>
|
||||
</ol>
|
||||
|
||||
|
@ -63,6 +63,13 @@ class OOMEntityState:
|
||||
complete = 4
|
||||
|
||||
|
||||
class OOMEntityType:
|
||||
"""Enum for the type of the OOM"""
|
||||
unknown = 0
|
||||
automatic = 1
|
||||
manual = 2
|
||||
|
||||
|
||||
def is_visible(element):
|
||||
return element.offsetWidth > 0 and element.offsetHeight > 0
|
||||
|
||||
@ -79,6 +86,18 @@ def show_element(element_id):
|
||||
element.classList.remove('js-text--display-none')
|
||||
|
||||
|
||||
def hide_elements(selector):
|
||||
"""Hide all matching elements by adding class js-text--display-none"""
|
||||
for element in document.querySelectorAll(selector):
|
||||
element.classList.add('js-text--display-none')
|
||||
|
||||
|
||||
def show_elements(selector):
|
||||
"""Show all matching elements by removing class js-text--display-none"""
|
||||
for element in document.querySelectorAll(selector):
|
||||
element.classList.remove('js-text--display-none')
|
||||
|
||||
|
||||
def toggle(element_id):
|
||||
"""Toggle the visibility of the given HTML element"""
|
||||
element = document.getElementById(element_id)
|
||||
@ -420,6 +439,13 @@ class OOMResult:
|
||||
:type: OOMEntityState
|
||||
"""
|
||||
|
||||
oom_type = OOMEntityType.unknown
|
||||
"""
|
||||
Type of this OOM (manually or automatically triggered)
|
||||
|
||||
:type: OOMEntityType
|
||||
"""
|
||||
|
||||
error_msg = ""
|
||||
"""
|
||||
Error message
|
||||
@ -450,7 +476,7 @@ class OOMAnalyser:
|
||||
r'^(?P<trigger_proc_name>[\S ]+) invoked oom-killer: '
|
||||
r'gfp_mask=(?P<trigger_proc_gfp_mask>0x[a-z0-9]+)(\((?P<trigger_proc_gfp_flags>[A-Z_|]+)\))?, '
|
||||
r'(nodemask=(?P<trigger_proc_nodemask>([\d,-]+|\(null\))), )?'
|
||||
r'order=(?P<trigger_proc_order>\d+), '
|
||||
r'order=(?P<trigger_proc_order>-?\d+), '
|
||||
r'oom_score_adj=(?P<trigger_proc_oomscore>\d+)',
|
||||
True,
|
||||
),
|
||||
@ -674,6 +700,11 @@ class OOMAnalyser:
|
||||
'does not find anything. This will cause subsequent errors.'.format(k, pattern))
|
||||
# __pragma__ ('nojsiter')
|
||||
|
||||
if self.oom_result.details['trigger_proc_order'] == "-1":
|
||||
self.oom_result.oom_type = OOMEntityType.manual
|
||||
else:
|
||||
self.oom_result.oom_type = OOMEntityType.automatic
|
||||
|
||||
self.oom_result.details['hardware_info'] = self._extract_block_from_next_pos('Hardware name:')
|
||||
|
||||
# strip "Call Trace" line at beginning and remove leading spaces
|
||||
@ -1308,16 +1339,13 @@ Killed process 6576 (mysqld) total-vm:33914892kB, anon-rss:20629004kB, file-rss:
|
||||
def set_HTML_defaults(self):
|
||||
"""Reset the HTML document but don't clean elements"""
|
||||
# hide all elements marked to be hidden by default
|
||||
for element in document.querySelectorAll('.js-text--default-hide'):
|
||||
element.classList.add('js-text--display-none')
|
||||
hide_elements('.js-text--default-hide')
|
||||
|
||||
# show all elements marked to be shown by default
|
||||
for element in document.querySelectorAll('.js-text--default-show'):
|
||||
element.classList.remove('js-text--display-none')
|
||||
show_elements('.js-text--default-show')
|
||||
|
||||
# show hidden rows
|
||||
for element in document.querySelectorAll('table .js-text--display-none'):
|
||||
element.classList.remove('js-text--display-none')
|
||||
show_elements('table .js-text--display-none')
|
||||
|
||||
# clear notification box
|
||||
element = document.getElementById('notify_box')
|
||||
@ -1490,6 +1518,12 @@ Killed process 6576 (mysqld) total-vm:33914892kB, anon-rss:20629004kB, file-rss:
|
||||
|
||||
hide_element('input')
|
||||
show_element('analysis')
|
||||
if self.oom_result.oom_type == OOMEntityType.manual:
|
||||
hide_elements('.js-oom-automatic--show')
|
||||
show_elements('.js-oom-manual--show')
|
||||
else:
|
||||
show_elements('.js-oom-automatic--show')
|
||||
hide_elements('.js-oom-manual--show')
|
||||
|
||||
for item in self.oom_result.details.keys():
|
||||
# ignore internal items
|
||||
|
15
test.py
15
test.py
@ -190,6 +190,10 @@ class TestInBrowser(TestBase):
|
||||
swap_total_kb = self.driver.find_element_by_class_name('swap_total_kb')
|
||||
self.assertEqual(swap_total_kb.text, '8388604 kBytes')
|
||||
|
||||
explanation = self.driver.find_element_by_id('explanation')
|
||||
self.assertTrue('OOM killer was automatically triggered' in explanation.text,
|
||||
'Missing text "OOM killer was automatically triggered"')
|
||||
|
||||
def test_010_load_page(self):
|
||||
"""Test if the page is loading"""
|
||||
assert "OOM Analyser" in self.driver.title
|
||||
@ -291,6 +295,17 @@ Killed process 6576 (java) total-vm:33914892kB, anon-rss:20629004kB, file-rss:0k
|
||||
self.check_results()
|
||||
self.click_reset()
|
||||
|
||||
def test_070_manually_triggered_OOM(self):
|
||||
"""Test for manually triggered OOM"""
|
||||
example = OOMAnalyser.OOMDisplay.example
|
||||
example = example.replace('order=0', 'order=-1')
|
||||
self.analyse_oom(example)
|
||||
self.assert_on_warn_error()
|
||||
|
||||
explanation = self.driver.find_element_by_id('explanation')
|
||||
self.assertTrue('OOM killer was manually triggered' in explanation.text,
|
||||
'Missing text "OOM killer was manually triggered"')
|
||||
|
||||
|
||||
class TestPython(TestBase):
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user