Skip to content

Commit

Permalink
#557 (NetBSD): various refactorings
Browse files Browse the repository at this point in the history
  • Loading branch information
giampaolo committed Jan 8, 2016
1 parent bc6cf43 commit e44d5e4
Show file tree
Hide file tree
Showing 6 changed files with 59 additions and 90 deletions.
5 changes: 3 additions & 2 deletions docs/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
Old 1.2.1 documentation is still available
`here <https://code.google.com/p/psutil/wiki/Documentation>`__.
.. versionchanged:: 3.3.0 added support for OpenBSD
.. versionchanged:: 3.4.0 added support for NetBSD

psutil documentation
====================
Expand Down Expand Up @@ -206,7 +207,7 @@ Memory
* **sout**: the number of bytes the system has swapped out from disk
(cumulative)

**sin** and **sout** on Windows are meaningless and are always set to ``0``.
**sin** and **sout** on Windows, OpenBSD and NetBSD are always set to ``0``.
See `examples/meminfo.py <https://github.com/giampaolo/psutil/blob/master/examples/meminfo.py>`__
script providing an example on how to convert bytes in a human readable form.

Expand Down Expand Up @@ -1043,7 +1044,7 @@ Process class
...]
>>>

Availability: All platforms except OpenBSD.
Availability: All platforms except OpenBSD and NetBSD.

.. method:: children(recursive=False)

Expand Down
9 changes: 6 additions & 3 deletions psutil/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -123,8 +123,9 @@
elif sys.platform.startswith("darwin"):
from . import _psosx as _psplatform

elif sys.platform.startswith("freebsd") or sys.platform.startswith("openbsd") \
or sys.platform.startswith("netbsd"):
elif sys.platform.startswith("freebsd") or \
sys.platform.startswith("openbsd") or \
sys.platform.startswith("netbsd"):
from . import _psbsd as _psplatform

elif sys.platform.startswith("sunos"):
Expand Down Expand Up @@ -969,7 +970,9 @@ def memory_percent(self):
except ZeroDivisionError:
return 0.0

if not _OPENBSD:
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.
Expand Down
80 changes: 42 additions & 38 deletions psutil/_psbsd.py
Original file line number Diff line number Diff line change
Expand Up @@ -521,66 +521,67 @@ def io_counters(self):
rc, wc, rb, wb = cext.proc_io_counters(self.pid)
return _common.pio(rc, wc, rb, wb)

@wrap_exceptions
def cwd(self):
"""Return process current working directory."""
# sometimes we get an empty string, in which case we turn
# it into None
if OPENBSD and self.pid == 0:
return None # ...else it would raise EINVAL
elif NETBSD:
try:
return os.readlink("/proc/%s/cwd" % self.pid)
except OSError as err:
if err.errno == errno.ENOENT:
if not pid_exists(self.pid):
raise NoSuchProcess(self.pid, self._name)
else:
raise ZombieProcess(
self.pid, self._name, self._ppid)
else:
raise
elif hasattr(cext, 'proc_open_files'):
# FreeBSD < 8 does not support functions based on
# kinfo_getfile() and kinfo_getvmmap()
return cext.proc_cwd(self.pid) or None
else:
raise NotImplementedError(
"supported only starting from FreeBSD 8" if
FREEBSD else "")

nt_mmap_grouped = namedtuple(
'mmap', 'path rss, private, ref_count, shadow_count')
nt_mmap_ext = namedtuple(
'mmap', 'addr, perms path rss, private, ref_count, shadow_count')

def _not_implemented(self):
raise NotImplementedError

# FreeBSD < 8 does not support functions based on kinfo_getfile()
# and kinfo_getvmmap()
if hasattr(cext, 'proc_open_files'):

@wrap_exceptions
def open_files(self):
"""Return files opened by process as a list of namedtuples."""
rawlist = cext.proc_open_files(self.pid)
return [_common.popenfile(path, fd) for path, fd in rawlist]
else:
open_files = _not_implemented

@wrap_exceptions
def cwd(self):
"""Return process current working directory."""
# sometimes we get an empty string, in which case we turn
# it into None
if OPENBSD and self.pid == 0:
return None # ...else it would raise EINVAL
elif NETBSD:
try:
return os.readlink("/proc/%s/cwd" % self.pid)
except OSError as err:
if err.errno == errno.ENOENT:
if not pid_exists(self.pid):
raise NoSuchProcess(self.pid, self._name)
else:
raise ZombieProcess(
self.pid, self._name, self._ppid)
else:
raise
else:
return cext.proc_cwd(self.pid) or None

@wrap_exceptions
def memory_maps(self):
if FREEBSD:
return cext.proc_memory_maps(self.pid)
else:
# TODO
raise NotImplementedError

# FreeBSD < 8 does not support functions based on kinfo_getfile()
# and kinfo_getvmmap()
if hasattr(cext, 'proc_num_fds'):
@wrap_exceptions
def num_fds(self):
"""Return the number of file descriptors opened by this process."""
return cext.proc_num_fds(self.pid)

else:
def _not_implemented(self):
raise NotImplementedError("supported only starting from FreeBSD 8")

open_files = _not_implemented
proc_cwd = _not_implemented
memory_maps = _not_implemented
num_fds = _not_implemented

# --- FreeBSD only APIs

if FREEBSD:

@wrap_exceptions
def cpu_affinity_get(self):
return cext.proc_cpu_affinity_get(self.pid)
Expand Down Expand Up @@ -609,3 +610,6 @@ def cpu_affinity_set(self, cpus):
"invalid CPU #%i (choose between %s)" % (
cpu, allcpus))
raise

def memory_maps(self):
return cext.proc_memory_maps(self.pid)
2 changes: 1 addition & 1 deletion psutil/_psutil_bsd.c
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
* OpenBSD references:
* - OpenBSD source code: http://anoncvs.spacehopper.org/openbsd-src/
*
* OpenBSD: missing compared to FreeBSD implementation:
* OpenBSD / NetBSD: missing APIs compared to FreeBSD implementation:
* - psutil.net_connections()
* - psutil.Process.get/set_cpu_affinity() (not supported natively)
* - psutil.Process.memory_maps()
Expand Down
49 changes: 5 additions & 44 deletions psutil/arch/bsd/netbsd.c
Original file line number Diff line number Diff line change
Expand Up @@ -461,7 +461,8 @@ psutil_swap_mem(PyObject *self, PyObject *args) {
return Py_BuildValue("(iiiii)", 0, 0, 0, 0, 0);
}

if ((swdev = calloc(nswap, sizeof(*swdev))) == NULL) {
swdev = calloc(nswap, sizeof(*swdev));
if (swdev == NULL) {
PyErr_SetFromErrno(PyExc_OSError);
return NULL;
}
Expand Down Expand Up @@ -511,40 +512,6 @@ psutil_proc_num_fds(PyObject *self, PyObject *args) {
}


// see sys/kern/kern_sysctl.c lines 1100 and
// usr.bin/fstat/fstat.c print_inet_details()
static char *
psutil_convert_ipv4(int family, uint32_t addr[4]) {
struct in_addr a;
memcpy(&a, addr, sizeof(a));
return inet_ntoa(a);
}


static char *
psutil_inet6_addrstr(struct in6_addr *p) {
struct sockaddr_in6 sin6;
static char hbuf[NI_MAXHOST];
const int niflags = NI_NUMERICHOST;

memset(&sin6, 0, sizeof(sin6));
sin6.sin6_family = AF_INET6;
sin6.sin6_len = sizeof(struct sockaddr_in6);
sin6.sin6_addr = *p;
if (IN6_IS_ADDR_LINKLOCAL(p) &&
*(u_int16_t *)&sin6.sin6_addr.s6_addr[2] != 0) {
sin6.sin6_scope_id =
ntohs(*(u_int16_t *)&sin6.sin6_addr.s6_addr[2]);
sin6.sin6_addr.s6_addr[2] = sin6.sin6_addr.s6_addr[3] = 0;
}

if (getnameinfo((struct sockaddr *)&sin6, sin6.sin6_len,
hbuf, sizeof(hbuf), NULL, 0, niflags))
return "invalid";

return hbuf;
}

PyObject *
psutil_per_cpu_times(PyObject *self, PyObject *args) {
static int maxcpus;
Expand All @@ -553,13 +520,11 @@ psutil_per_cpu_times(PyObject *self, PyObject *args) {
size_t len;
size_t size;
int i;
PyObject *py_retlist = PyList_New(0);
PyObject *py_cputime = NULL;
PyObject *py_retlist = PyList_New(0);

if (py_retlist == NULL)
return NULL;


// retrieve the number of cpus
mib[0] = CTL_HW;
mib[1] = HW_NCPU;
Expand Down Expand Up @@ -610,12 +575,11 @@ psutil_disk_io_counters(PyObject *self, PyObject *args) {
int i, dk_ndrive, mib[3];
size_t len;
struct io_sysctl *stats;

PyObject *py_retdict = PyDict_New();
PyObject *py_disk_info = NULL;
PyObject *py_retdict = PyDict_New();

if (py_retdict == NULL)
return NULL;

mib[0] = CTL_HW;
mib[1] = HW_IOSTATS;
mib[2] = sizeof(struct io_sysctl);
Expand All @@ -629,12 +593,10 @@ psutil_disk_io_counters(PyObject *self, PyObject *args) {

stats = malloc(len);
if (stats == NULL) {
warn("can't malloc");
PyErr_NoMemory();
goto error;
}
if (sysctl(mib, 2, stats, &len, NULL, 0) < 0 ) {
warn("could not read HW_IOSTATS");
PyErr_SetFromErrno(PyExc_OSError);
goto error;
}
Expand Down Expand Up @@ -667,4 +629,3 @@ psutil_disk_io_counters(PyObject *self, PyObject *args) {
free(stats);
return NULL;
}

4 changes: 2 additions & 2 deletions test/test_psutil.py
Original file line number Diff line number Diff line change
Expand Up @@ -1670,7 +1670,7 @@ def test_memory_info(self):
# def test_memory_info_ex(self):
# # tested later in fetch all test suite

@unittest.skipIf(OPENBSD, "not available on OpenBSD")
@unittest.skipIf(OPENBSD or NETBSD, "not available on this platform")
def test_memory_maps(self):
p = psutil.Process()
maps = p.memory_maps()
Expand Down Expand Up @@ -3122,7 +3122,7 @@ def test_netstat(self):
def test_ifconfig(self):
self.assert_stdout('ifconfig.py')

@unittest.skipIf(OPENBSD, "OpenBSD does not support memory maps")
@unittest.skipIf(OPENBSD or NETBSD, "memory maps not supported")
def test_pmap(self):
self.assert_stdout('pmap.py', args=str(os.getpid()))

Expand Down

0 comments on commit e44d5e4

Please sign in to comment.