Skip to content
This repository has been archived by the owner on Jun 22, 2024. It is now read-only.

Commit

Permalink
Merge pull request #57 from giampaolo/master
Browse files Browse the repository at this point in the history
[pull] master from giampaolo:master
  • Loading branch information
ddelange committed Dec 21, 2023
2 parents c677cb1 + 13e1fe7 commit fbcd240
Show file tree
Hide file tree
Showing 9 changed files with 265 additions and 175 deletions.
13 changes: 13 additions & 0 deletions HISTORY.rst
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,19 @@
5.9.8 (IN DEVELOPMENT)
======================

**Enhancements**

- 2343_, [FreeBSD]: filter `net_connections()`_ returned list in C instead of
Python, and avoid to retrieve unnecessary connection types unless explicitly
asked. E.g., on an IDLE system with few IPv6 connections this will run around
4 times faster. Before all connection types (TCP, UDP, UNIX) were retrieved
internally, even if only a portion was returned.
- 2342_, [NetBSD]: same as above (#2343) but for NetBSD.

**Bug fixes**

- 930_, [NetBSD], [critical]: `net_connections()`_ implementation was broken.
It could either leak memory or core dump.
- 2340_, [NetBSD]: if process is terminated, `Process.cwd()`_ will return an
empty string instead of raising `NoSuchProcess`_.

Expand Down
2 changes: 1 addition & 1 deletion INSTALL.rst
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ RedHat / CentOS::

Alpine::

sudo apk add gcc python3-dev
sudo apk add gcc python3-dev musl-dev linux-headers
pip install --no-binary :all: psutil

Windows (build)
Expand Down
15 changes: 5 additions & 10 deletions psutil/_psbsd.py
Original file line number Diff line number Diff line change
Expand Up @@ -426,16 +426,12 @@ def net_connections(kind):
if OPENBSD:
rawlist = cext.net_connections(-1, families, types)
elif NETBSD:
rawlist = cext.net_connections(-1)
rawlist = cext.net_connections(-1, kind)
else: # FreeBSD
rawlist = cext.net_connections()
rawlist = cext.net_connections(families, types)

for item in rawlist:
fd, fam, type, laddr, raddr, status, pid = item
if NETBSD or FREEBSD:
# OpenBSD implements filtering in C
if (fam not in families) or (type not in types):
continue
nt = conn_to_ntuple(fd, fam, type, laddr, raddr,
status, TCP_STATUSES, pid)
ret.add(nt)
Expand Down Expand Up @@ -786,16 +782,15 @@ def connections(self, kind='inet'):
ret = []

if NETBSD:
rawlist = cext.net_connections(self.pid)
rawlist = cext.net_connections(self.pid, kind)
elif OPENBSD:
rawlist = cext.net_connections(self.pid, families, types)
else: # FreeBSD
else:
rawlist = cext.proc_connections(self.pid, families, types)

for item in rawlist:
fd, fam, type, laddr, raddr, status = item[:6]
if NETBSD:
# FreeBSD and OpenBSD implement filtering in C
if FREEBSD:
if (fam not in families) or (type not in types):
continue
nt = conn_to_ntuple(fd, fam, type, laddr, raddr, status,
Expand Down
83 changes: 72 additions & 11 deletions psutil/arch/freebsd/sys_socks.c
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ static struct xfile *psutil_xfiles;
static int psutil_nxfiles;


int
static int
psutil_populate_xfiles(void) {
size_t len;

Expand Down Expand Up @@ -61,7 +61,7 @@ psutil_populate_xfiles(void) {
}


struct xfile *
static struct xfile *
psutil_get_file_from_sock(kvaddr_t sock) {
struct xfile *xf;
int n;
Expand All @@ -76,7 +76,10 @@ psutil_get_file_from_sock(kvaddr_t sock) {

// Reference:
// https://github.com/freebsd/freebsd/blob/master/usr.bin/sockstat/sockstat.c
int psutil_gather_inet(int proto, PyObject *py_retlist) {
static int
psutil_gather_inet(
int proto, int include_v4, int include_v6, PyObject *py_retlist)
{
struct xinpgen *xig, *exig;
struct xinpcb *xip;
struct xtcpcb *xtp;
Expand Down Expand Up @@ -177,6 +180,12 @@ int psutil_gather_inet(int proto, PyObject *py_retlist) {
goto error;
}

// filter
if ((inp->inp_vflag & INP_IPV4) && (include_v4 == 0))
continue;
if ((inp->inp_vflag & INP_IPV6) && (include_v6 == 0))
continue;

char lip[200], rip[200];

xf = psutil_get_file_from_sock(so->xso_so);
Expand Down Expand Up @@ -235,7 +244,8 @@ int psutil_gather_inet(int proto, PyObject *py_retlist) {
}


int psutil_gather_unix(int proto, PyObject *py_retlist) {
static int
psutil_gather_unix(int proto, PyObject *py_retlist) {
struct xunpgen *xug, *exug;
struct xunpcb *xup;
const char *varname = NULL;
Expand Down Expand Up @@ -339,23 +349,74 @@ int psutil_gather_unix(int proto, PyObject *py_retlist) {
}


static int
psutil_int_in_seq(int value, PyObject *py_seq) {
int inseq;
PyObject *py_value;

py_value = PyLong_FromLong((long)value);
if (py_value == NULL)
return -1;
inseq = PySequence_Contains(py_seq, py_value); // return -1 on failure
Py_DECREF(py_value);
return inseq;
}


PyObject*
psutil_net_connections(PyObject* self, PyObject* args) {
// Return system-wide open connections.
int include_v4, include_v6, include_unix, include_tcp, include_udp;
PyObject *py_af_filter = NULL;
PyObject *py_type_filter = NULL;
PyObject *py_retlist = PyList_New(0);

if (py_retlist == NULL)
return NULL;
if (psutil_populate_xfiles() != 1)
if (! PyArg_ParseTuple(args, "OO", &py_af_filter, &py_type_filter)) {
goto error;
}
if (!PySequence_Check(py_af_filter) || !PySequence_Check(py_type_filter)) {
PyErr_SetString(PyExc_TypeError, "arg 2 or 3 is not a sequence");
goto error;
}

if ((include_v4 = psutil_int_in_seq(AF_INET, py_af_filter)) == -1)
goto error;
if (psutil_gather_inet(IPPROTO_TCP, py_retlist) == 0)
if ((include_v6 = psutil_int_in_seq(AF_INET6, py_af_filter)) == -1)
goto error;
if (psutil_gather_inet(IPPROTO_UDP, py_retlist) == 0)
if ((include_unix = psutil_int_in_seq(AF_UNIX, py_af_filter)) == -1)
goto error;
if (psutil_gather_unix(SOCK_STREAM, py_retlist) == 0)
goto error;
if (psutil_gather_unix(SOCK_DGRAM, py_retlist) == 0)
if ((include_tcp = psutil_int_in_seq(SOCK_STREAM, py_type_filter)) == -1)
goto error;
if ((include_udp = psutil_int_in_seq(SOCK_DGRAM, py_type_filter)) == -1)
goto error;

if (psutil_populate_xfiles() != 1)
goto error;

// TCP
if (include_tcp == 1) {
if (psutil_gather_inet(
IPPROTO_TCP, include_v4, include_v6, py_retlist) == 0)
{
goto error;
}
}
// UDP
if (include_udp == 1) {
if (psutil_gather_inet(
IPPROTO_UDP, include_v4, include_v6, py_retlist) == 0)
{
goto error;
}
}
// UNIX
if (include_unix == 1) {
if (psutil_gather_unix(SOCK_STREAM, py_retlist) == 0)
goto error;
if (psutil_gather_unix(SOCK_DGRAM, py_retlist) == 0)
goto error;
}

free(psutil_xfiles);
return py_retlist;
Expand Down
12 changes: 6 additions & 6 deletions psutil/arch/netbsd/proc.c
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ psutil_proc_cwd(PyObject *self, PyObject *args) {
char path[MAXPATHLEN];
size_t pathlen = sizeof path;

if (! PyArg_ParseTuple(args, "l", &pid))
if (! PyArg_ParseTuple(args, _Py_PARSE_PID, &pid))
return NULL;

#ifdef KERN_PROC_CWD
Expand All @@ -116,7 +116,7 @@ psutil_proc_cwd(PyObject *self, PyObject *args) {
free(buf);
if (len == -1) {
if (errno == ENOENT)
NoSuchProcess("sysctl -> ENOENT");
NoSuchProcess("readlink -> ENOENT");
else
PyErr_SetFromErrno(PyExc_OSError);
return NULL;
Expand All @@ -143,7 +143,7 @@ psutil_proc_exe(PyObject *self, PyObject *args) {
int ret;
size_t size;
if (! PyArg_ParseTuple(args, "l", &pid))
if (! PyArg_ParseTuple(args, _Py_PARSE_PID, &pid))
return NULL;
if (pid == 0) {
// else returns ENOENT
Expand Down Expand Up @@ -190,7 +190,7 @@ psutil_proc_num_threads(PyObject *self, PyObject *args) {
// Return number of threads used by process as a Python integer.
long pid;
kinfo_proc kp;
if (! PyArg_ParseTuple(args, "l", &pid))
if (! PyArg_ParseTuple(args, _Py_PARSE_PID, &pid))
return NULL;
if (psutil_kinfo_proc(pid, &kp) == -1)
return NULL;
Expand All @@ -211,7 +211,7 @@ psutil_proc_threads(PyObject *self, PyObject *args) {

if (py_retlist == NULL)
return NULL;
if (! PyArg_ParseTuple(args, "l", &pid))
if (! PyArg_ParseTuple(args, _Py_PARSE_PID, &pid))
goto error;

mib[0] = CTL_KERN;
Expand Down Expand Up @@ -396,7 +396,7 @@ psutil_proc_num_fds(PyObject *self, PyObject *args) {

struct kinfo_file *freep;

if (! PyArg_ParseTuple(args, "l", &pid))
if (! PyArg_ParseTuple(args, _Py_PARSE_PID, &pid))
return NULL;

errno = 0;
Expand Down
Loading

0 comments on commit fbcd240

Please sign in to comment.