| # This tool lists processes that lock memory pages from swapping to disk. | 
 |  | 
 | import re | 
 |  | 
 | import psutil | 
 |  | 
 |  | 
 | LCK_SUMMARY_REGEX = re.compile( | 
 |     "^VmLck:\s+(?P<locked>[\d]+)\s+kB", re.MULTILINE) | 
 |  | 
 |  | 
 | def main(): | 
 |     try: | 
 |         print(_get_report()) | 
 |     except Exception as e: | 
 |         print("Failure listing processes locking memory: %s" % str(e)) | 
 |         raise | 
 |  | 
 |  | 
 | def _get_report(): | 
 |     mlock_users = [] | 
 |     for proc in psutil.process_iter(): | 
 |         # sadly psutil does not expose locked pages info, that's why we | 
 |         # iterate over the /proc/%pid/status files manually | 
 |         try: | 
 |             s = open("%s/%d/status" % (psutil.PROCFS_PATH, proc.pid), 'r') | 
 |             with s: | 
 |                 for line in s: | 
 |                     result = LCK_SUMMARY_REGEX.search(line) | 
 |                     if result: | 
 |                         locked = int(result.group('locked')) | 
 |                         if locked: | 
 |                             mlock_users.append({'name': proc.name(), | 
 |                                                 'pid': proc.pid, | 
 |                                                 'locked': locked}) | 
 |         except OSError: | 
 |             # pids can disappear, we're ok with that | 
 |             continue | 
 |  | 
 |  | 
 |     # produce a single line log message with per process mlock stats | 
 |     if mlock_users: | 
 |         return "; ".join( | 
 |             "[%(name)s (pid:%(pid)s)]=%(locked)dKB" % args | 
 |             # log heavy users first | 
 |             for args in sorted(mlock_users, key=lambda d: d['locked']) | 
 |         ) | 
 |     else: | 
 |         return "no locked memory" | 
 |  | 
 |  | 
 | if __name__ == "__main__": | 
 |     main() |