summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGiampaolo Rodola <g.rodola@gmail.com>2019-02-27 14:32:21 +0100
committerGiampaolo Rodola <g.rodola@gmail.com>2019-02-27 14:32:21 +0100
commitb31f3bf778004f1eae6ac552dd8eb8419664ac73 (patch)
treeacddc47b163b688da55a2857e62dfb5253623d2c
parente827bf46381d3d996d63e064834aa421e502d8b8 (diff)
downloadpsutil-b31f3bf778004f1eae6ac552dd8eb8419664ac73.tar.gz
#1291 / OSX: mark memory_maps() as deprecated and make it alwats raise AccessDenied
-rw-r--r--HISTORY.rst5
-rw-r--r--docs/index.rst67
-rw-r--r--psutil/__init__.py1
-rw-r--r--psutil/_common.py2
-rw-r--r--psutil/_psaix.py5
-rw-r--r--psutil/_psosx.py13
-rw-r--r--psutil/_psutil_osx.c160
-rw-r--r--psutil/tests/__init__.py2
-rwxr-xr-xpsutil/tests/test_contracts.py10
-rwxr-xr-xpsutil/tests/test_osx.py3
-rwxr-xr-xpsutil/tests/test_process.py4
11 files changed, 56 insertions, 216 deletions
diff --git a/HISTORY.rst b/HISTORY.rst
index 26eff418..5313a091 100644
--- a/HISTORY.rst
+++ b/HISTORY.rst
@@ -40,6 +40,11 @@ XXXX-XX-XX
- 1439_: [NetBSD] Process.connections() may return incomplete results if using
oneshot()
+**API changes**
+
+- 1291_: [OSX] Process.memory_maps() is deprecated and will always raise
+ AccessDenied. It will be removed in psutil 6.0.0.
+
5.5.1
=====
diff --git a/docs/index.rst b/docs/index.rst
index 78a88f97..6d464c85 100644
--- a/docs/index.rst
+++ b/docs/index.rst
@@ -1675,48 +1675,47 @@ Process class
See `pmap.py <https://github.com/giampaolo/psutil/blob/master/scripts/pmap.py>`__
for an example application.
- +---------------+--------------+---------+-----------+--------------+
- | Linux | macOS | Windows | Solaris | FreeBSD |
- +===============+==============+=========+===========+==============+
- | rss | rss | rss | rss | rss |
- +---------------+--------------+---------+-----------+--------------+
- | size | private | | anonymous | private |
- +---------------+--------------+---------+-----------+--------------+
- | pss | swapped | | locked | ref_count |
- +---------------+--------------+---------+-----------+--------------+
- | shared_clean | dirtied | | | shadow_count |
- +---------------+--------------+---------+-----------+--------------+
- | shared_dirty | ref_count | | | |
- +---------------+--------------+---------+-----------+--------------+
- | private_clean | shadow_depth | | | |
- +---------------+--------------+---------+-----------+--------------+
- | private_dirty | | | | |
- +---------------+--------------+---------+-----------+--------------+
- | referenced | | | | |
- +---------------+--------------+---------+-----------+--------------+
- | anonymous | | | | |
- +---------------+--------------+---------+-----------+--------------+
- | swap | | | | |
- +---------------+--------------+---------+-----------+--------------+
+ +---------------+---------+--------------+-----------+
+ | Linux | Windows | FreeBSD | Solaris |
+ +===============+=========+==============+===========+
+ | rss | rss | rss | rss |
+ +---------------+---------+--------------+-----------+
+ | size | | private | anonymous |
+ +---------------+---------+--------------+-----------+
+ | pss | | ref_count | locked |
+ +---------------+---------+--------------+-----------+
+ | shared_clean | | shadow_count | |
+ +---------------+---------+--------------+-----------+
+ | shared_dirty | | | |
+ +---------------+---------+--------------+-----------+
+ | private_clean | | | |
+ +---------------+---------+--------------+-----------+
+ | private_dirty | | | |
+ +---------------+---------+--------------+-----------+
+ | referenced | | | |
+ +---------------+---------+--------------+-----------+
+ | anonymous | | | |
+ +---------------+---------+--------------+-----------+
+ | swap | | | |
+ +---------------+---------+--------------+-----------+
>>> import psutil
>>> p = psutil.Process()
>>> p.memory_maps()
[pmmap_grouped(path='/lib/x8664-linux-gnu/libutil-2.15.so', rss=32768, size=2125824, pss=32768, shared_clean=0, shared_dirty=0, private_clean=20480, private_dirty=12288, referenced=32768, anonymous=12288, swap=0),
pmmap_grouped(path='/lib/x8664-linux-gnu/libc-2.15.so', rss=3821568, size=3842048, pss=3821568, shared_clean=0, shared_dirty=0, private_clean=0, private_dirty=3821568, referenced=3575808, anonymous=3821568, swap=0),
- pmmap_grouped(path='/lib/x8664-linux-gnu/libcrypto.so.0.1', rss=34124, rss=32768, size=2134016, pss=15360, shared_clean=24576, shared_dirty=0, private_clean=0, private_dirty=8192, referenced=24576, anonymous=8192, swap=0),
- pmmap_grouped(path='[heap]', rss=32768, size=139264, pss=32768, shared_clean=0, shared_dirty=0, private_clean=0, private_dirty=32768, referenced=32768, anonymous=32768, swap=0),
- pmmap_grouped(path='[stack]', rss=2465792, size=2494464, pss=2465792, shared_clean=0, shared_dirty=0, private_clean=0, private_dirty=2465792, referenced=2277376, anonymous=2465792, swap=0),
- ...]
- >>> p.memory_maps(grouped=False)
- [pmmap_ext(addr='00400000-006ea000', perms='r-xp', path='/usr/bin/python2.7', rss=2293760, size=3055616, pss=1157120, shared_clean=2273280, shared_dirty=0, private_clean=20480, private_dirty=0, referenced=2293760, anonymous=0, swap=0),
- pmmap_ext(addr='008e9000-008eb000', perms='r--p', path='/usr/bin/python2.7', rss=8192, size=8192, pss=6144, shared_clean=4096, shared_dirty=0, private_clean=0, private_dirty=4096, referenced=8192, anonymous=4096, swap=0),
- pmmap_ext(addr='008eb000-00962000', perms='rw-p', path='/usr/bin/python2.7', rss=417792, size=487424, pss=317440, shared_clean=200704, shared_dirty=0, private_clean=16384, private_dirty=200704, referenced=417792, anonymous=200704, swap=0),
- pmmap_ext(addr='00962000-00985000', perms='rw-p', path='[anon]', rss=139264, size=143360, pss=139264, shared_clean=0, shared_dirty=0, private_clean=0, private_dirty=139264, referenced=139264, anonymous=139264, swap=0),
- pmmap_ext(addr='02829000-02ccf000', perms='rw-p', path='[heap]', rss=4743168, size=4874240, pss=4743168, shared_clean=0, shared_dirty=0, private_clean=0, private_dirty=4743168, referenced=4718592, anonymous=4743168, swap=0),
...]
- Availability: All platforms except OpenBSD, NetBSD and AIX.
+ Availability: Linux, Windows, FreeBSD, SunOS
+
+ .. warning::
+ on macOS, starting from version 5.6.0, this function is deprecated and
+ will always raise :class:`psutil.AccessDenied`. It is scheduled for
+ removal in 6.0.0
+ (see `issue 1020 <https://github.com/giampaolo/psutil/issues/1291#issuecomment-467828376>`_).
+
+ .. versionchanged::
+ 5.6.0 deprecated on macOS, always raise AccessDenied
.. method:: children(recursive=False)
diff --git a/psutil/__init__.py b/psutil/__init__.py
index 447e507b..d8ec701c 100644
--- a/psutil/__init__.py
+++ b/psutil/__init__.py
@@ -1218,7 +1218,6 @@ class Process(object):
return (value / float(total_phymem)) * 100
if hasattr(_psplatform.Process, "memory_maps"):
- # Available everywhere except OpenBSD and NetBSD.
def memory_maps(self, grouped=True):
"""Return process' mapped memory regions as a list of namedtuples
whose fields are variable depending on the platform.
diff --git a/psutil/_common.py b/psutil/_common.py
index b809a79f..6d430388 100644
--- a/psutil/_common.py
+++ b/psutil/_common.py
@@ -475,7 +475,7 @@ def deprecated_method(replacement):
@functools.wraps(fun)
def inner(self, *args, **kwargs):
- warnings.warn(msg, category=FutureWarning, stacklevel=2)
+ warnings.warn(msg, category=DeprecationWarning, stacklevel=2)
return getattr(self, replacement)(*args, **kwargs)
return inner
return outer
diff --git a/psutil/_psaix.py b/psutil/_psaix.py
index 58ecf17f..96ed9476 100644
--- a/psutil/_psaix.py
+++ b/psutil/_psaix.py
@@ -97,11 +97,6 @@ pfullmem = pmem
scputimes = namedtuple('scputimes', ['user', 'system', 'idle', 'iowait'])
# psutil.virtual_memory()
svmem = namedtuple('svmem', ['total', 'available', 'percent', 'used', 'free'])
-# psutil.Process.memory_maps(grouped=True)
-pmmap_grouped = namedtuple('pmmap_grouped', ['path', 'rss', 'anon', 'locked'])
-# psutil.Process.memory_maps(grouped=False)
-pmmap_ext = namedtuple(
- 'pmmap_ext', 'addr perms ' + ' '.join(pmmap_grouped._fields))
# =====================================================================
diff --git a/psutil/_psosx.py b/psutil/_psosx.py
index 72b343f5..78f710aa 100644
--- a/psutil/_psosx.py
+++ b/psutil/_psosx.py
@@ -8,6 +8,7 @@ import contextlib
import errno
import functools
import os
+import warnings
from socket import AF_INET
from collections import namedtuple
@@ -107,13 +108,6 @@ svmem = namedtuple(
pmem = namedtuple('pmem', ['rss', 'vms', 'pfaults', 'pageins'])
# psutil.Process.memory_full_info()
pfullmem = namedtuple('pfullmem', pmem._fields + ('uss', ))
-# psutil.Process.memory_maps(grouped=True)
-pmmap_grouped = namedtuple(
- 'pmmap_grouped',
- 'path rss private swapped dirtied ref_count shadow_depth')
-# psutil.Process.memory_maps(grouped=False)
-pmmap_ext = namedtuple(
- 'pmmap_ext', 'addr perms ' + ' '.join(pmmap_grouped._fields))
# =====================================================================
@@ -582,6 +576,7 @@ class Process(object):
retlist.append(ntuple)
return retlist
- @wrap_exceptions
def memory_maps(self):
- return cext.proc_memory_maps(self.pid)
+ msg = "memory_maps() on OSX is deprecated and will be removed in 6.0.0"
+ warnings.warn(msg, category=DeprecationWarning, stacklevel=2)
+ raise AccessDenied(self.pid, msg=msg)
diff --git a/psutil/_psutil_osx.c b/psutil/_psutil_osx.c
index 02b2172d..eaf4e514 100644
--- a/psutil/_psutil_osx.c
+++ b/psutil/_psutil_osx.c
@@ -342,164 +342,6 @@ psutil_proc_environ(PyObject *self, PyObject *args) {
/*
- * Return a list of tuples for every process memory maps.
- * 'procstat' cmdline utility has been used as an example.
- * This will fail for all processes except os.getpid(),
- * even as root.
- */
-static PyObject *
-psutil_proc_memory_maps(PyObject *self, PyObject *args) {
- char buf[PATH_MAX];
- char addr_str[34];
- char perms[8];
- int pagesize = getpagesize();
- int iteration = 0;
- long pid;
- kern_return_t kr;
- mach_port_t task = MACH_PORT_NULL;
- uint32_t depth = 1;
- vm_address_t address = 0;
- vm_size_t size = 0;
- struct vm_region_submap_info_64 info;
- mach_msg_type_number_t count = VM_REGION_SUBMAP_INFO_COUNT_64;
- PyObject *py_tuple = NULL;
- PyObject *py_path = NULL;
- PyObject *py_list = PyList_New(0);
-
- if (py_list == NULL)
- return NULL;
- if (! PyArg_ParseTuple(args, "l", &pid))
- goto error;
- if (psutil_task_for_pid(pid, &task) != 0)
- goto error;
-
- while (1) {
- iteration += 1;
- py_tuple = NULL;
- kr = vm_region_recurse_64(task, &address, &size, &depth,
- (vm_region_info_64_t)&info, &count);
- if (kr != KERN_SUCCESS) {
- if ((kr == KERN_INVALID_ADDRESS) && (iteration > 1)) {
- break; // no more regions to read
- }
- PyErr_Format(
- PyExc_RuntimeError,
- "vm_region_recurse_64() failed: %s",
- mach_error_string(kr));
- goto error;
- }
-
- if (info.is_submap) {
- depth++;
- }
- else {
- // Free/Reset the char[]s to avoid weird paths
- memset(buf, 0, sizeof(buf));
- memset(addr_str, 0, sizeof(addr_str));
- memset(perms, 0, sizeof(perms));
-
- sprintf(addr_str,
- "%016lx-%016lx",
- (long unsigned int)address,
- (long unsigned int)address + size);
- sprintf(perms, "%c%c%c/%c%c%c",
- (info.protection & VM_PROT_READ) ? 'r' : '-',
- (info.protection & VM_PROT_WRITE) ? 'w' : '-',
- (info.protection & VM_PROT_EXECUTE) ? 'x' : '-',
- (info.max_protection & VM_PROT_READ) ? 'r' : '-',
- (info.max_protection & VM_PROT_WRITE) ? 'w' : '-',
- (info.max_protection & VM_PROT_EXECUTE) ? 'x' : '-');
-
- // proc_regionfilename() is undocumented but from its source
- // code we can determine that it sets errno on error and
- // return length of path.
- errno = 0;
- proc_regionfilename((pid_t)pid, address, buf, sizeof(buf));
- if (errno != 0) {
- psutil_debug("proc_regionfilename() failed errno=%i", errno);
- psutil_raise_for_pid(pid, "proc_regionfilename()");
- goto error;
- }
-
- if (info.share_mode == SM_COW && info.ref_count == 1) {
- // Treat single reference SM_COW as SM_PRIVATE
- info.share_mode = SM_PRIVATE;
- }
-
- if (strlen(buf) == 0) {
- switch (info.share_mode) {
-// #ifdef SM_LARGE_PAGE
- // case SM_LARGE_PAGE:
- // Treat SM_LARGE_PAGE the same as SM_PRIVATE
- // since they are not shareable and are wired.
-// #endif
- case SM_COW:
- strcpy(buf, "[cow]");
- break;
- case SM_PRIVATE:
- strcpy(buf, "[prv]");
- break;
- case SM_EMPTY:
- strcpy(buf, "[nul]");
- break;
- case SM_SHARED:
- case SM_TRUESHARED:
- strcpy(buf, "[shm]");
- break;
- case SM_PRIVATE_ALIASED:
- strcpy(buf, "[ali]");
- break;
- case SM_SHARED_ALIASED:
- strcpy(buf, "[s/a]");
- break;
- default:
- strcpy(buf, "[???]");
- }
- }
-
- py_path = PyUnicode_DecodeFSDefault(buf);
- if (! py_path)
- goto error;
- py_tuple = Py_BuildValue(
- "ssOIIIIIH",
- addr_str, // "start-end"address
- perms, // "rwx" permissions
- py_path, // path
- info.pages_resident * pagesize, // rss
- info.pages_shared_now_private * pagesize, // private
- info.pages_swapped_out * pagesize, // swapped
- info.pages_dirtied * pagesize, // dirtied
- info.ref_count, // ref count
- info.shadow_depth // shadow depth
- );
- if (!py_tuple)
- goto error;
- if (PyList_Append(py_list, py_tuple))
- goto error;
- Py_DECREF(py_tuple);
- Py_DECREF(py_path);
-
- // increment address for the next map/file
- address += size;
- }
- }
-
- if (task != MACH_PORT_NULL)
- mach_port_deallocate(mach_task_self(), task);
-
- return py_list;
-
-error:
- if (task != MACH_PORT_NULL)
- mach_port_deallocate(mach_task_self(), task);
- Py_XDECREF(py_tuple);
- Py_XDECREF(py_path);
- Py_DECREF(py_list);
- return NULL;
-}
-
-
-/*
* Return the number of logical CPUs in the system.
* XXX this could be shared with BSD.
*/
@@ -1931,8 +1773,6 @@ PsutilMethods[] = {
"Return the number of fds opened by process."},
{"proc_connections", psutil_proc_connections, METH_VARARGS,
"Get process TCP and UDP connections as a list of tuples"},
- {"proc_memory_maps", psutil_proc_memory_maps, METH_VARARGS,
- "Return a list of tuples for every process's memory map"},
// --- system-related functions
diff --git a/psutil/tests/__init__.py b/psutil/tests/__init__.py
index 545f5f25..86af2cfb 100644
--- a/psutil/tests/__init__.py
+++ b/psutil/tests/__init__.py
@@ -167,7 +167,7 @@ HAS_ENVIRON = hasattr(psutil.Process, "environ")
HAS_PROC_IO_COUNTERS = hasattr(psutil.Process, "io_counters")
HAS_IONICE = hasattr(psutil.Process, "ionice")
HAS_MEMORY_FULL_INFO = 'uss' in psutil.Process().memory_full_info()._fields
-HAS_MEMORY_MAPS = hasattr(psutil.Process, "memory_maps")
+HAS_MEMORY_MAPS = not MACOS and hasattr(psutil.Process, "memory_maps")
HAS_PROC_CPU_NUM = hasattr(psutil.Process, "cpu_num")
HAS_RLIMIT = hasattr(psutil.Process, "rlimit")
HAS_THREADS = hasattr(psutil.Process, "threads")
diff --git a/psutil/tests/test_contracts.py b/psutil/tests/test_contracts.py
index 5ea4ba1c..97a1a0f0 100755
--- a/psutil/tests/test_contracts.py
+++ b/psutil/tests/test_contracts.py
@@ -181,10 +181,18 @@ class TestDeprecations(unittest.TestCase):
with warnings.catch_warnings(record=True) as ws:
psutil.Process().memory_info_ex()
w = ws[0]
- self.assertIsInstance(w.category(), FutureWarning)
+ self.assertIsInstance(w.category(), DeprecationWarning)
self.assertIn("memory_info_ex() is deprecated", str(w.message))
self.assertIn("use memory_info() instead", str(w.message))
+ @unittest.skipIf(not MACOS, "deprecated on macOS")
+ def test_memory_maps_osx(self):
+ with warnings.catch_warnings(record=True) as ws:
+ with self.assertRaises(psutil.AccessDenied):
+ psutil.Process().memory_maps()
+ w = ws[0]
+ self.assertIsInstance(w.category(), DeprecationWarning)
+
# ===================================================================
# --- System API types
diff --git a/psutil/tests/test_osx.py b/psutil/tests/test_osx.py
index cf5c5ea8..40257190 100755
--- a/psutil/tests/test_osx.py
+++ b/psutil/tests/test_osx.py
@@ -158,9 +158,6 @@ class TestZombieProcessAPIs(unittest.TestCase):
self.assertRaises((psutil.ZombieProcess, psutil.AccessDenied),
self.p.threads)
- def test_memory_maps(self):
- self.assertRaises(psutil.ZombieProcess, self.p.memory_maps)
-
@unittest.skipIf(not MACOS, "MACOS only")
class TestSystemAPIs(unittest.TestCase):
diff --git a/psutil/tests/test_process.py b/psutil/tests/test_process.py
index 16c0ba4a..31f42eba 100755
--- a/psutil/tests/test_process.py
+++ b/psutil/tests/test_process.py
@@ -1265,7 +1265,7 @@ class TestProcess(unittest.TestCase):
p.send_signal(signal.CTRL_BREAK_EVENT)
excluded_names = ['pid', 'is_running', 'wait', 'create_time',
- 'oneshot']
+ 'oneshot', 'memory_info_ex']
if LINUX and not HAS_RLIMIT:
excluded_names.append('rlimit')
for name in dir(p):
@@ -1291,6 +1291,8 @@ class TestProcess(unittest.TestCase):
ret = meth([0])
elif name == 'send_signal':
ret = meth(signal.SIGTERM)
+ elif MACOS and name == 'memory_maps':
+ continue # XXX
else:
ret = meth()
except psutil.ZombieProcess: