Browse code

Replace pmap shellout with pure python implementation

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

Dirk Mueller authored on 2017/09/10 09:51:10
Showing 1 changed files
... ...
@@ -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: