Package: python-psutil
Version: 2.1.1-1+b1
Severity: important
Tags: patch

When using psutil to query system statistics, several function leak a file
handle by returning without closing the file handle.

When this is used on a regular basis, the system will fail with too many open
file handles:

eg.

def per_cpu_times():
    """Return a list of namedtuple representing the CPU times
    for every CPU available on the system.
    """
    cpus = []
    f = open('/proc/stat', 'rb')
    try:
        # get rid of the first line which refers to system wide CPU stats
        f.readline()
        CPU = b('cpu')
        for line in f:
            if line.startswith(CPU):
                values = line.split()
                fields = values[1:len(scputimes._fields) + 1]
                fields = [float(x) / CLOCK_TICKS for x in fields]
                entry = scputimes(*fields)
                cpus.append(entry)
        return cpus
    finally:
        f.close()



-- System Information:
Debian Release: 8.0
  APT prefers unstable
  APT policy: (500, 'unstable'), (500, 'stable'), (1, 'experimental')
Architecture: amd64 (x86_64)
Foreign Architectures: i386

Kernel: Linux 3.17-1-amd64 (SMP w/4 CPU cores)
Locale: LANG=en_US.UTF-8, LC_CTYPE=en_US.UTF-8 (charmap=UTF-8)
Shell: /bin/sh linked to /bin/dash
Init: systemd (via /run/systemd/system)

Versions of packages python-psutil depends on:
ii  libc6       2.19-13
ii  python      2.7.8-2
pn  python:any  <none>

python-psutil recommends no packages.

python-psutil suggests no packages.

-- no debconf information
This message is subject to the following terms and conditions: MAIL 
DISCLAIMER<http://www.barco.com/en/maildisclaimer>
Description: pslinux leaks several filehandles by returning prematurely
 This patch closes the filehandles before returning. An alternative way
 of handling this more cleanly, but a bit larger rewrite, would be to
 use use a with statement. This would be more clean.
 .
 python-psutil (2.1.1-1+barco2) unstable; urgency=low
 .
   * patch for misc filehandle leaks in pslinux
Author: Marc Leeman <marc.lee...@barco.com>

--- python-psutil-2.1.1.orig/psutil/_pslinux.py
+++ python-psutil-2.1.1/psutil/_pslinux.py
@@ -248,6 +248,7 @@ def per_cpu_times():
                 fields = [float(x) / CLOCK_TICKS for x in fields]
                 entry = scputimes(*fields)
                 cpus.append(entry)
+	f.close()
         return cpus
     finally:
         f.close()
@@ -339,6 +340,7 @@ def boot_time():
             if line.startswith(BTIME):
                 ret = float(line.strip().split()[1])
                 BOOT_TIME = ret
+		f.close()
                 return ret
         raise RuntimeError("line 'btime' not found")
     finally:
@@ -768,7 +770,9 @@ class Process(object):
             f = open(fname, "rt")
         try:
             # return the args as a list
-            return [x for x in f.read().split('\x00') if x]
+	    r = [x for x in f.read().split('\x00') if x]
+	    f.close()
+            return r
         finally:
             f.close()
 
@@ -862,6 +866,7 @@ class Process(object):
         f = open("/proc/%s/statm" % self.pid, 'rb')
         try:
             vms, rss = f.readline().split()[:2]
+	    f.close()
             return _common.pmem(int(rss) * PAGESIZE,
                                 int(vms) * PAGESIZE)
         finally:
@@ -990,6 +995,7 @@ class Process(object):
                 elif line.startswith(NON_VOLUNTARY):
                     unvol = int(line.split()[1])
                 if vol is not None and unvol is not None:
+		    f.close()
                     return _common.pctxsw(vol, unvol)
             raise NotImplementedError(
                 "'voluntary_ctxt_switches' and 'nonvoluntary_ctxt_switches'"
@@ -1005,6 +1011,7 @@ class Process(object):
             THREADS = b("Threads:")
             for line in f:
                 if line.startswith(THREADS):
+		    f.close()
                     return int(line.split()[1])
             raise NotImplementedError("line not found")
         finally:
@@ -1140,7 +1147,9 @@ class Process(object):
                         letter = letter.decode()
                     # XXX is '?' legit? (we're not supposed to return
                     # it anyway)
-                    return PROC_STATUSES.get(letter, '?')
+		    r  = PROC_STATUSES.get(letter, '?')
+		    f.close()
+		    return r
         finally:
             f.close()
 
@@ -1193,6 +1202,7 @@ class Process(object):
             for line in f:
                 if line.startswith(PPID):
                     # PPid: nnnn
+		    f.close()
                     return int(line.split()[1])
             raise NotImplementedError("line not found")
         finally:
@@ -1206,7 +1216,9 @@ class Process(object):
             for line in f:
                 if line.startswith(UID):
                     _, real, effective, saved, fs = line.split()
-                    return _common.puids(int(real), int(effective), int(saved))
+		    r = _common.puids(int(real), int(effective), int(saved))
+		    f.close()
+		    return r
             raise NotImplementedError("line not found")
         finally:
             f.close()
@@ -1219,7 +1231,9 @@ class Process(object):
             for line in f:
                 if line.startswith(GID):
                     _, real, effective, saved, fs = line.split()
-                    return _common.pgids(int(real), int(effective), int(saved))
+		    r = _common.pgids(int(real), int(effective), int(saved))
+		    f.close()
+		    return r
             raise NotImplementedError("line not found")
         finally:
             f.close()

Reply via email to