Without this patch, the pmap -XX call fails on openSUSE Leap
distributions as those have a fairly ancient procps version that
does not support the -XX parameter. A pure python implementation
is more portable, faster and even shorter than the subprocess
call.
Closes-Bug: #1716066
Change-Id: I2fdb457e65359a1c9d40452c922cfdca0e6e74dc
| ... | ... |
@@ -3,12 +3,12 @@ |
| 3 | 3 |
# This tool lists processes that lock memory pages from swapping to disk. |
| 4 | 4 |
|
| 5 | 5 |
import re |
| 6 |
-import subprocess |
|
| 7 | 6 |
|
| 8 | 7 |
import psutil |
| 9 | 8 |
|
| 10 | 9 |
|
| 11 |
-SUMMARY_REGEX = re.compile(b".*\s+(?P<locked>[\d]+)\s+KB") |
|
| 10 |
+LCK_SUMMARY_REGEX = re.compile( |
|
| 11 |
+ "^VmLck:\s+(?P<locked>[\d]+)\s+kB", re.MULTILINE) |
|
| 12 | 12 |
|
| 13 | 13 |
|
| 14 | 14 |
def main(): |
| ... | ... |
@@ -22,28 +22,21 @@ def main(): |
| 22 | 22 |
def _get_report(): |
| 23 | 23 |
mlock_users = [] |
| 24 | 24 |
for proc in psutil.process_iter(): |
| 25 |
- pid = proc.pid |
|
| 26 | 25 |
# sadly psutil does not expose locked pages info, that's why we |
| 27 |
- # call to pmap and parse the output here |
|
| 26 |
+ # iterate over the /proc/%pid/status files manually |
|
| 28 | 27 |
try: |
| 29 |
- out = subprocess.check_output(['pmap', '-XX', str(pid)]) |
|
| 30 |
- except subprocess.CalledProcessError as e: |
|
| 31 |
- # 42 means process just vanished, which is ok |
|
| 32 |
- if e.returncode == 42: |
|
| 33 |
- continue |
|
| 34 |
- raise |
|
| 35 |
- last_line = out.splitlines()[-1] |
|
| 36 |
- |
|
| 37 |
- # some processes don't provide a memory map, for example those |
|
| 38 |
- # running as kernel services, so we need to skip those that don't |
|
| 39 |
- # match |
|
| 40 |
- result = SUMMARY_REGEX.match(last_line) |
|
| 41 |
- if result: |
|
| 42 |
- locked = int(result.group('locked'))
|
|
| 43 |
- if locked: |
|
| 44 |
- mlock_users.append({'name': proc.name(),
|
|
| 45 |
- 'pid': pid, |
|
| 46 |
- 'locked': locked}) |
|
| 28 |
+ s = open("%s/%d/status" % (psutil.PROCFS_PATH, proc.pid), 'r')
|
|
| 29 |
+ except EnvironmentError: |
|
| 30 |
+ continue |
|
| 31 |
+ with s: |
|
| 32 |
+ for line in s: |
|
| 33 |
+ result = LCK_SUMMARY_REGEX.search(line) |
|
| 34 |
+ if result: |
|
| 35 |
+ locked = int(result.group('locked'))
|
|
| 36 |
+ if locked: |
|
| 37 |
+ mlock_users.append({'name': proc.name(),
|
|
| 38 |
+ 'pid': proc.pid, |
|
| 39 |
+ 'locked': locked}) |
|
| 47 | 40 |
|
| 48 | 41 |
# produce a single line log message with per process mlock stats |
| 49 | 42 |
if mlock_users: |