diff options
author | Giampaolo Rodola <g.rodola@gmail.com> | 2020-10-23 19:57:17 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-10-23 19:57:17 +0200 |
commit | 89ae354ab7704db69a3f6c880234d21719558511 (patch) | |
tree | b8a87ef018d4f0e7cef48111bfe001390224ba8c | |
parent | ba083a0eea87331b67b57c3c83e8cc53faa12b10 (diff) | |
download | psutil-89ae354ab7704db69a3f6c880234d21719558511.tar.gz |
[FreeBSD] process resource limits (#1859) (#809)
-rw-r--r-- | HISTORY.rst | 3 | ||||
-rw-r--r-- | docs/_static/css/custom.css | 2 | ||||
-rw-r--r-- | docs/index.rst | 85 | ||||
-rw-r--r-- | psutil/__init__.py | 72 | ||||
-rw-r--r-- | psutil/_psbsd.py | 12 | ||||
-rw-r--r-- | psutil/_pslinux.py | 6 | ||||
-rw-r--r-- | psutil/_psutil_bsd.c | 4 | ||||
-rw-r--r-- | psutil/_psutil_linux.c | 43 | ||||
-rw-r--r-- | psutil/_psutil_posix.c | 99 | ||||
-rw-r--r-- | psutil/arch/freebsd/specific.c | 85 | ||||
-rw-r--r-- | psutil/arch/freebsd/specific.h | 2 | ||||
-rwxr-xr-x | psutil/tests/test_bsd.py | 1 | ||||
-rwxr-xr-x | psutil/tests/test_contracts.py | 30 | ||||
-rwxr-xr-x | psutil/tests/test_process.py | 5 | ||||
-rwxr-xr-x | scripts/procinfo.py | 5 |
15 files changed, 303 insertions, 151 deletions
diff --git a/HISTORY.rst b/HISTORY.rst index 1ef5573a..d92dce73 100644 --- a/HISTORY.rst +++ b/HISTORY.rst @@ -7,7 +7,8 @@ XXXX-XX-XX **Enhancements** -- 893_: implement `Process.environ()` on BSD family. (patch by Armin Gruner) +- 809_: [FreeBSD] add support for `Process.rlimit()`. +- 893_: [BSD] add support for `Process.environ()` (patch by Armin Gruner) - 1830_: [UNIX] `net_if_stats()`'s `isup` also checks whether the NIC is running (meaning Wi-Fi or ethernet cable is connected). (patch by Chris Burger) - 1837_: [Linux] improved battery detection and charge "secsleft" calculation diff --git a/docs/_static/css/custom.css b/docs/_static/css/custom.css index c5c201e4..e88f5307 100644 --- a/docs/_static/css/custom.css +++ b/docs/_static/css/custom.css @@ -4,7 +4,7 @@ } .rst-content dl:not(.docutils) { - margin: 0px 0px 0px 0px; + margin: 0px 0px 0px 0px !important; } .data dd { diff --git a/docs/index.rst b/docs/index.rst index 3898f9da..c4ff6a25 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -1348,16 +1348,17 @@ Process class >>> import psutil >>> p = psutil.Process() - >>> # process may open no more than 128 file descriptors - >>> p.rlimit(psutil.RLIMIT_NOFILE, (128, 128)) - >>> # process may create files no bigger than 1024 bytes - >>> p.rlimit(psutil.RLIMIT_FSIZE, (1024, 1024)) - >>> # get - >>> p.rlimit(psutil.RLIMIT_FSIZE) + >>> p.rlimit(psutil.RLIMIT_NOFILE, (128, 128)) # process can open max 128 file descriptors + >>> p.rlimit(psutil.RLIMIT_FSIZE, (1024, 1024)) # can create files no bigger than 1024 bytes + >>> p.rlimit(psutil.RLIMIT_FSIZE) # get (1024, 1024) >>> - Availability: Linux + Also see `procinfo.py`_ script. + + Availability: Linux, FreeBSD + + .. versionchanged:: 5.7.3 added FreeBSD support .. method:: io_counters() @@ -2247,29 +2248,43 @@ Process priority constants Process resources constants --------------------------- -.. data:: RLIM_INFINITY -.. data:: RLIMIT_AS -.. data:: RLIMIT_CORE -.. data:: RLIMIT_CPU -.. data:: RLIMIT_DATA -.. data:: RLIMIT_FSIZE -.. data:: RLIMIT_LOCKS -.. data:: RLIMIT_MEMLOCK -.. data:: RLIMIT_MSGQUEUE -.. data:: RLIMIT_NICE -.. data:: RLIMIT_NOFILE -.. data:: RLIMIT_NPROC -.. data:: RLIMIT_RSS -.. data:: RLIMIT_RTPRIO -.. data:: RLIMIT_RTTIME -.. data:: RLIMIT_SIGPENDING -.. data:: RLIMIT_STACK - - Constants used for getting and setting process resource limits to be used in - conjunction with :meth:`psutil.Process.rlimit()`. See `man prlimit`_ for - further information. +Linux / FreeBSD: - Availability: Linux + .. data:: RLIM_INFINITY + .. data:: RLIMIT_AS + .. data:: RLIMIT_CORE + .. data:: RLIMIT_CPU + .. data:: RLIMIT_DATA + .. data:: RLIMIT_FSIZE + .. data:: RLIMIT_MEMLOCK + .. data:: RLIMIT_NOFILE + .. data:: RLIMIT_NPROC + .. data:: RLIMIT_RSS + .. data:: RLIMIT_STACK + +Linux specific: + + .. data:: RLIMIT_LOCKS + .. data:: RLIMIT_MSGQUEUE + .. data:: RLIMIT_NICE + .. data:: RLIMIT_RTPRIO + .. data:: RLIMIT_RTTIME + .. data:: RLIMIT_SIGPENDING + +FreeBSD specific: + + .. data:: RLIMIT_SWAP + .. data:: RLIMIT_SBSIZE + .. data:: RLIMIT_NPTS + +Constants used for getting and setting process resource limits to be used in +conjunction with :meth:`psutil.Process.rlimit()`. See `resource.getrlimit`_ +for further information. + +Availability: Linux, FreeBSD + +.. versionchanged:: 5.7.3 added FreeBSD support, added ``RLIMIT_SWAP``, + ``RLIMIT_SBSIZE``, ``RLIMIT_NPTS``. Connections constants --------------------- @@ -2513,11 +2528,6 @@ Security To report a security vulnerability, please use the `Tidelift security contact`_. Tidelift will coordinate the fix and disclosure. -.. _`Giampaolo Rodola`: https://gmpy.dev/about -.. _`donation`: https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=A9ZS7PKKRM3S8 -.. _Tidelift security contact: https://tidelift.com/security -.. _Tidelift Subscription: https://tidelift.com/subscription/pkg/pypi-psutil?utm_source=pypi-psutil&utm_medium=referral&utm_campaign=readme - Development guide ================= @@ -2874,13 +2884,12 @@ Timeline .. _`cpu_distribution.py`: https://github.com/giampaolo/psutil/blob/master/scripts/cpu_distribution.py .. _`development guide`: https://github.com/giampaolo/psutil/blob/master/docs/DEVGUIDE.rst .. _`disk_usage.py`: https://github.com/giampaolo/psutil/blob/master/scripts/disk_usage.py -.. _`donation`: https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=A9ZS7PKKRM3S8 .. _`enum`: https://docs.python.org/3/library/enum.html#module-enum .. _`fans.py`: https://github.com/giampaolo/psutil/blob/master/scripts/fans.py .. _`GetDriveType`: https://docs.microsoft.com/en-us/windows/desktop/api/fileapi/nf-fileapi-getdrivetypea +.. _`GetExitCodeProcess`: https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-getexitcodeprocess .. _`getfsstat`: http://www.manpagez.com/man/2/getfsstat/ .. _`GetPriorityClass`: https://docs.microsoft.com/en-us/windows/desktop/api/processthreadsapi/nf-processthreadsapi-getpriorityclass -.. _`GetExitCodeProcess`: https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-getexitcodeprocess .. _`Giampaolo Rodola`: https://gmpy.dev/about .. _`hash`: https://docs.python.org/3/library/functions.html#hash .. _`ifconfig.py`: https://github.com/giampaolo/psutil/blob/master/scripts/ifconfig.py @@ -2908,6 +2917,7 @@ Timeline .. _`os.times`: https://docs.python.org//library/os.html#os.times .. _`pmap.py`: https://github.com/giampaolo/psutil/blob/master/scripts/pmap.py .. _`PROCESS_MEMORY_COUNTERS_EX`: https://docs.microsoft.com/en-us/windows/desktop/api/psapi/ns-psapi-_process_memory_counters_ex +.. _`procinfo.py`: https://github.com/giampaolo/psutil/blob/master/scripts/procinfo.py .. _`procsmem.py`: https://github.com/giampaolo/psutil/blob/master/scripts/procsmem.py .. _`resource.getrlimit`: https://docs.python.org/3/library/resource.html#resource.getrlimit .. _`resource.setrlimit`: https://docs.python.org/3/library/resource.html#resource.setrlimit @@ -2920,9 +2930,10 @@ Timeline .. _`SOCK_SEQPACKET`: https://docs.python.org/3/library/socket.html#socket.SOCK_SEQPACKET .. _`SOCK_STREAM`: https://docs.python.org/3/library/socket.html#socket.SOCK_STREAM .. _`socket.fromfd`: https://docs.python.org/3/library/socket.html#socket.fromfd -.. _`subprocess.Popen`: https://docs.python.org/3/library/subprocess.html#subprocess.Popen .. _`subprocess.Popen.wait`: https://docs.python.org/3/library/subprocess.html#subprocess.Popen.wait +.. _`subprocess.Popen`: https://docs.python.org/3/library/subprocess.html#subprocess.Popen .. _`temperatures.py`: https://github.com/giampaolo/psutil/blob/master/scripts/temperatures.py .. _`TerminateProcess`: https://docs.microsoft.com/en-us/windows/desktop/api/processthreadsapi/nf-processthreadsapi-terminateprocess .. _Tidelift security contact: https://tidelift.com/security .. _Tidelift Subscription: https://tidelift.com/subscription/pkg/pypi-psutil?utm_source=pypi-psutil&utm_medium=referral&utm_campaign=readme +.. _Tidelift Subscription: https://tidelift.com/subscription/pkg/pypi-psutil?utm_source=pypi-psutil&utm_medium=referral&utm_campaign=readme diff --git a/psutil/__init__.py b/psutil/__init__.py index 2108a40e..cc4e79cc 100644 --- a/psutil/__init__.py +++ b/psutil/__init__.py @@ -102,44 +102,6 @@ if LINUX: from ._pslinux import IOPRIO_CLASS_IDLE # NOQA from ._pslinux import IOPRIO_CLASS_NONE # NOQA from ._pslinux import IOPRIO_CLASS_RT # NOQA - # Linux >= 2.6.36 - if _psplatform.HAS_PRLIMIT: - from ._psutil_linux import RLIM_INFINITY # NOQA - from ._psutil_linux import RLIMIT_AS # NOQA - from ._psutil_linux import RLIMIT_CORE # NOQA - from ._psutil_linux import RLIMIT_CPU # NOQA - from ._psutil_linux import RLIMIT_DATA # NOQA - from ._psutil_linux import RLIMIT_FSIZE # NOQA - from ._psutil_linux import RLIMIT_LOCKS # NOQA - from ._psutil_linux import RLIMIT_MEMLOCK # NOQA - from ._psutil_linux import RLIMIT_NOFILE # NOQA - from ._psutil_linux import RLIMIT_NPROC # NOQA - from ._psutil_linux import RLIMIT_RSS # NOQA - from ._psutil_linux import RLIMIT_STACK # NOQA - # Kinda ugly but considerably faster than using hasattr() and - # setattr() against the module object (we are at import time: - # speed matters). - from . import _psutil_linux - try: - RLIMIT_MSGQUEUE = _psutil_linux.RLIMIT_MSGQUEUE - except AttributeError: - pass - try: - RLIMIT_NICE = _psutil_linux.RLIMIT_NICE - except AttributeError: - pass - try: - RLIMIT_RTPRIO = _psutil_linux.RLIMIT_RTPRIO - except AttributeError: - pass - try: - RLIMIT_RTTIME = _psutil_linux.RLIMIT_RTTIME - except AttributeError: - pass - try: - RLIMIT_SIGPENDING = _psutil_linux.RLIMIT_SIGPENDING - except AttributeError: - pass elif WINDOWS: from . import _pswindows as _psplatform @@ -197,6 +159,7 @@ __all__ = [ "CONN_ESTABLISHED", "CONN_SYN_SENT", "CONN_SYN_RECV", "CONN_FIN_WAIT1", "CONN_FIN_WAIT2", "CONN_TIME_WAIT", "CONN_CLOSE", "CONN_CLOSE_WAIT", "CONN_LAST_ACK", "CONN_LISTEN", "CONN_CLOSING", "CONN_NONE", + # "CONN_IDLE", "CONN_BOUND", "AF_LINK", @@ -207,6 +170,11 @@ __all__ = [ "BSD", "FREEBSD", "LINUX", "NETBSD", "OPENBSD", "MACOS", "OSX", "POSIX", "SUNOS", "WINDOWS", "AIX", + # "RLIM_INFINITY", "RLIMIT_AS", "RLIMIT_CORE", "RLIMIT_CPU", "RLIMIT_DATA", + # "RLIMIT_FSIZE", "RLIMIT_LOCKS", "RLIMIT_MEMLOCK", "RLIMIT_NOFILE", + # "RLIMIT_NPROC", "RLIMIT_RSS", "RLIMIT_STACK", "RLIMIT_MSGQUEUE", + # "RLIMIT_NICE", "RLIMIT_RTPRIO", "RLIMIT_RTTIME", "RLIMIT_SIGPENDING", + # classes "Process", "Popen", @@ -222,9 +190,22 @@ __all__ = [ "users", "boot_time", # others ] +__all__.extend(_psplatform.__extra__all__) + +if LINUX or FREEBSD: + # Populate global namespace with RLIM* constants. + from . import _psutil_posix + + _globals = globals() + _name = None + for _name in dir(_psutil_posix): + if _name.startswith('RLIM') and _name.isupper(): + _globals[_name] = getattr(_psutil_posix, _name) + __all__.append(_name) + del _globals, _name + AF_LINK = _psplatform.AF_LINK -__all__.extend(_psplatform.__extra__all__) __author__ = "Giampaolo Rodola'" __version__ = "5.7.3" version_info = tuple([int(num) for num in __version__.split('.')]) @@ -801,7 +782,7 @@ class Process(object): else: return self._proc.ionice_set(ioclass, value) - # Linux only + # Linux / FreeBSD only if hasattr(_psplatform.Process, "rlimit"): def rlimit(self, resource, limits=None): @@ -809,15 +790,12 @@ class Process(object): tuple. *resource* is one of the RLIMIT_* constants. - *limits* is supposed to be a (soft, hard) tuple. + *limits* is supposed to be a (soft, hard) tuple. See "man prlimit" for further info. - Available on Linux only. + Available on Linux and FreeBSD only. """ - if limits is None: - return self._proc.rlimit(resource) - else: - return self._proc.rlimit(resource, limits) + return self._proc.rlimit(resource, limits) # Windows, Linux and FreeBSD only if hasattr(_psplatform.Process, "cpu_affinity_get"): @@ -831,7 +809,7 @@ class Process(object): (Windows, Linux and BSD only). """ if cpus is None: - return list(set(self._proc.cpu_affinity_get())) + return sorted(set(self._proc.cpu_affinity_get())) else: if not cpus: if hasattr(self._proc, "_get_eligible_cpus"): diff --git a/psutil/_psbsd.py b/psutil/_psbsd.py index 9565406b..428c8bde 100644 --- a/psutil/_psbsd.py +++ b/psutil/_psbsd.py @@ -904,3 +904,15 @@ class Process(object): @wrap_exceptions def memory_maps(self): return cext.proc_memory_maps(self.pid) + + @wrap_exceptions + def rlimit(self, resource, limits=None): + if limits is None: + return cext.proc_getrlimit(self.pid, resource) + else: + if len(limits) != 2: + raise ValueError( + "second argument must be a (soft, hard) tuple, " + "got %s" % repr(limits)) + soft, hard = limits + return cext.proc_setrlimit(self.pid, resource, soft, hard) diff --git a/psutil/_pslinux.py b/psutil/_pslinux.py index d5ce358c..683cef5d 100644 --- a/psutil/_pslinux.py +++ b/psutil/_pslinux.py @@ -80,12 +80,6 @@ HAS_PROC_IO_PRIORITY = hasattr(cext, "proc_ioprio_get") HAS_CPU_AFFINITY = hasattr(cext, "proc_cpu_affinity_get") _DEFAULT = object() -# RLIMIT_* constants, not guaranteed to be present on all kernels -if HAS_PRLIMIT: - for name in dir(cext): - if name.startswith('RLIM'): - __extra__all__.append(name) - # Number of clock ticks per second CLOCK_TICKS = os.sysconf("SC_CLK_TCK") PAGESIZE = os.sysconf("SC_PAGE_SIZE") diff --git a/psutil/_psutil_bsd.c b/psutil/_psutil_bsd.c index c4450d7d..6933260a 100644 --- a/psutil/_psutil_bsd.c +++ b/psutil/_psutil_bsd.c @@ -1097,6 +1097,10 @@ static PyMethodDef mod_methods[] = { "Return process CPU affinity."}, {"proc_cpu_affinity_set", psutil_proc_cpu_affinity_set, METH_VARARGS, "Set process CPU affinity."}, + {"proc_getrlimit", psutil_proc_getrlimit, METH_VARARGS, + "Get process resource limits."}, + {"proc_setrlimit", psutil_proc_setrlimit, METH_VARARGS, + "Set process resource limits."}, {"cpu_count_phys", psutil_cpu_count_phys, METH_VARARGS, "Return an XML string to determine the number physical CPUs."}, #endif diff --git a/psutil/_psutil_linux.c b/psutil/_psutil_linux.c index 41547438..4def9692 100644 --- a/psutil/_psutil_linux.c +++ b/psutil/_psutil_linux.c @@ -606,7 +606,6 @@ static PyMethodDef mod_methods[] = { void init_psutil_linux(void) #endif /* PY_MAJOR_VERSION */ { - PyObject *v; #if PY_MAJOR_VERSION >= 3 PyObject *mod = PyModule_Create(&moduledef); #else @@ -616,48 +615,6 @@ static PyMethodDef mod_methods[] = { INITERR; if (PyModule_AddIntConstant(mod, "version", PSUTIL_VERSION)) INITERR; -#if PSUTIL_HAVE_PRLIMIT - if (PyModule_AddIntConstant(mod, "RLIMIT_AS", RLIMIT_AS)) INITERR; - if (PyModule_AddIntConstant(mod, "RLIMIT_CORE", RLIMIT_CORE)) INITERR; - if (PyModule_AddIntConstant(mod, "RLIMIT_CPU", RLIMIT_CPU)) INITERR; - if (PyModule_AddIntConstant(mod, "RLIMIT_DATA", RLIMIT_DATA)) INITERR; - if (PyModule_AddIntConstant(mod, "RLIMIT_FSIZE", RLIMIT_FSIZE)) INITERR; - if (PyModule_AddIntConstant(mod, "RLIMIT_LOCKS", RLIMIT_LOCKS)) INITERR; - if (PyModule_AddIntConstant(mod, "RLIMIT_MEMLOCK", RLIMIT_MEMLOCK)) INITERR; - if (PyModule_AddIntConstant(mod, "RLIMIT_NOFILE", RLIMIT_NOFILE)) INITERR; - if (PyModule_AddIntConstant(mod, "RLIMIT_NPROC", RLIMIT_NPROC)) INITERR; - if (PyModule_AddIntConstant(mod, "RLIMIT_RSS", RLIMIT_RSS)) INITERR; - if (PyModule_AddIntConstant(mod, "RLIMIT_STACK", RLIMIT_STACK)) INITERR; - -#if defined(HAVE_LONG_LONG) - if (sizeof(RLIM_INFINITY) > sizeof(long)) { - v = PyLong_FromLongLong((PY_LONG_LONG) RLIM_INFINITY); - } else -#endif - { - v = PyLong_FromLong((long) RLIM_INFINITY); - } - if (v) { - PyModule_AddObject(mod, "RLIM_INFINITY", v); - } - -#ifdef RLIMIT_MSGQUEUE - if (PyModule_AddIntConstant(mod, "RLIMIT_MSGQUEUE", RLIMIT_MSGQUEUE)) INITERR; -#endif -#ifdef RLIMIT_NICE - if (PyModule_AddIntConstant(mod, "RLIMIT_NICE", RLIMIT_NICE)) INITERR; -#endif -#ifdef RLIMIT_RTPRIO - if (PyModule_AddIntConstant(mod, "RLIMIT_RTPRIO", RLIMIT_RTPRIO)) INITERR; -#endif -#ifdef RLIMIT_RTTIME - if (PyModule_AddIntConstant(mod, "RLIMIT_RTTIME", RLIMIT_RTTIME)) INITERR; -#endif -#ifdef RLIMIT_SIGPENDING - if (PyModule_AddIntConstant(mod, "RLIMIT_SIGPENDING", RLIMIT_SIGPENDING)) - INITERR; -#endif -#endif if (PyModule_AddIntConstant(mod, "DUPLEX_HALF", DUPLEX_HALF)) INITERR; if (PyModule_AddIntConstant(mod, "DUPLEX_FULL", DUPLEX_FULL)) INITERR; if (PyModule_AddIntConstant(mod, "DUPLEX_UNKNOWN", DUPLEX_UNKNOWN)) INITERR; diff --git a/psutil/_psutil_posix.c b/psutil/_psutil_posix.c index 1182765d..876b4129 100644 --- a/psutil/_psutil_posix.c +++ b/psutil/_psutil_posix.c @@ -41,6 +41,9 @@ #elif defined(PSUTIL_AIX) #include <netdb.h> #endif +#if defined(PSUTIL_LINUX) || defined(PSUTIL_FREEBSD) + #include <sys/resource.h> +#endif #include "_psutil_common.h" @@ -668,6 +671,102 @@ static PyMethodDef mod_methods[] = { if (PyModule_AddIntConstant(mod, "AF_LINK", AF_LINK)) INITERR; #endif +#if defined(PSUTIL_LINUX) || defined(PSUTIL_FREEBSD) + PyObject *v; + +#ifdef RLIMIT_AS + if (PyModule_AddIntConstant(mod, "RLIMIT_AS", RLIMIT_AS)) INITERR; +#endif + +#ifdef RLIMIT_CORE + if (PyModule_AddIntConstant(mod, "RLIMIT_CORE", RLIMIT_CORE)) INITERR; +#endif + +#ifdef RLIMIT_CPU + if (PyModule_AddIntConstant(mod, "RLIMIT_CPU", RLIMIT_CPU)) INITERR; +#endif + +#ifdef RLIMIT_DATA + if (PyModule_AddIntConstant(mod, "RLIMIT_DATA", RLIMIT_DATA)) INITERR; +#endif + +#ifdef RLIMIT_FSIZE + if (PyModule_AddIntConstant(mod, "RLIMIT_FSIZE", RLIMIT_FSIZE)) INITERR; +#endif + +#ifdef RLIMIT_MEMLOCK + if (PyModule_AddIntConstant(mod, "RLIMIT_MEMLOCK", RLIMIT_MEMLOCK)) INITERR; +#endif + +#ifdef RLIMIT_NOFILE + if (PyModule_AddIntConstant(mod, "RLIMIT_NOFILE", RLIMIT_NOFILE)) INITERR; +#endif + +#ifdef RLIMIT_NPROC + if (PyModule_AddIntConstant(mod, "RLIMIT_NPROC", RLIMIT_NPROC)) INITERR; +#endif + +#ifdef RLIMIT_RSS + if (PyModule_AddIntConstant(mod, "RLIMIT_RSS", RLIMIT_RSS)) INITERR; +#endif + +#ifdef RLIMIT_STACK + if (PyModule_AddIntConstant(mod, "RLIMIT_STACK", RLIMIT_STACK)) INITERR; +#endif + +// Linux specific + +#ifdef RLIMIT_LOCKS + if (PyModule_AddIntConstant(mod, "RLIMIT_LOCKS", RLIMIT_LOCKS)) INITERR; +#endif + +#ifdef RLIMIT_MSGQUEUE + if (PyModule_AddIntConstant(mod, "RLIMIT_MSGQUEUE", RLIMIT_MSGQUEUE)) INITERR; +#endif + +#ifdef RLIMIT_NICE + if (PyModule_AddIntConstant(mod, "RLIMIT_NICE", RLIMIT_NICE)) INITERR; +#endif + +#ifdef RLIMIT_RTPRIO + if (PyModule_AddIntConstant(mod, "RLIMIT_RTPRIO", RLIMIT_RTPRIO)) INITERR; +#endif + +#ifdef RLIMIT_RTTIME + if (PyModule_AddIntConstant(mod, "RLIMIT_RTTIME", RLIMIT_RTTIME)) INITERR; +#endif + +#ifdef RLIMIT_SIGPENDING + if (PyModule_AddIntConstant(mod, "RLIMIT_SIGPENDING", RLIMIT_SIGPENDING)) INITERR; +#endif + +// Free specific + +#ifdef RLIMIT_SWAP + if (PyModule_AddIntConstant(mod, "RLIMIT_SWAP", RLIMIT_SWAP)) INITERR; +#endif + +#ifdef RLIMIT_SBSIZE + if (PyModule_AddIntConstant(mod, "RLIMIT_SBSIZE", RLIMIT_SBSIZE)) INITERR; +#endif + +#ifdef RLIMIT_NPTS + if (PyModule_AddIntConstant(mod, "RLIMIT_NPTS", RLIMIT_NPTS)) INITERR; +#endif + +#if defined(HAVE_LONG_LONG) + if (sizeof(RLIM_INFINITY) > sizeof(long)) { + v = PyLong_FromLongLong((PY_LONG_LONG) RLIM_INFINITY); + } else +#endif + { + v = PyLong_FromLong((long) RLIM_INFINITY); + } + if (v) { + PyModule_AddObject(mod, "RLIM_INFINITY", v); + } +#endif // defined(PSUTIL_LINUX) || defined(PSUTIL_FREEBSD) + if (mod == NULL) INITERR; #if PY_MAJOR_VERSION >= 3 diff --git a/psutil/arch/freebsd/specific.c b/psutil/arch/freebsd/specific.c index c7832647..fcfce131 100644 --- a/psutil/arch/freebsd/specific.c +++ b/psutil/arch/freebsd/specific.c @@ -1077,3 +1077,88 @@ error: PyErr_SetFromErrno(PyExc_OSError); return NULL; } + + +/* + * An emulation of Linux prlimit(). Returns a (soft, hard) tuple. + */ +PyObject * +psutil_proc_getrlimit(PyObject *self, PyObject *args) { + pid_t pid; + int ret; + int resource; + size_t len; + int name[5]; + struct rlimit rlp; + + if (! PyArg_ParseTuple(args, _Py_PARSE_PID "i", &pid, &resource)) + return NULL; + + name[0] = CTL_KERN; + name[1] = KERN_PROC; + name[2] = KERN_PROC_RLIMIT; + name[3] = pid; + name[4] = resource; + len = sizeof(rlp); + + ret = sysctl(name, 5, &rlp, &len, NULL, 0); + if (ret == -1) + return PyErr_SetFromErrno(PyExc_OSError); + +#if defined(HAVE_LONG_LONG) + return Py_BuildValue("LL", + (PY_LONG_LONG) rlp.rlim_cur, + (PY_LONG_LONG) rlp.rlim_max); +#else + return Py_BuildValue("ll", + (long) rlp.rlim_cur, + (long) rlp.rlim_max); +#endif +} + + +/* + * An emulation of Linux prlimit() (set). + */ +PyObject * +psutil_proc_setrlimit(PyObject *self, PyObject *args) { + pid_t pid; + int ret; + int resource; + int name[5]; + struct rlimit new; + struct rlimit *newp = NULL; + PyObject *py_soft = NULL; + PyObject *py_hard = NULL; + + if (! PyArg_ParseTuple( + args, _Py_PARSE_PID "iOO", &pid, &resource, &py_soft, &py_hard)) + return NULL; + + name[0] = CTL_KERN; + name[1] = KERN_PROC; + name[2] = KERN_PROC_RLIMIT; + name[3] = pid; + name[4] = resource; + +#if defined(HAVE_LONG_LONG) + new.rlim_cur = PyLong_AsLongLong(py_soft); + if (new.rlim_cur == (rlim_t) - 1 && PyErr_Occurred()) + return NULL; + new.rlim_max = PyLong_AsLongLong(py_hard); + if (new.rlim_max == (rlim_t) - 1 && PyErr_Occurred()) + return NULL; +#else + new.rlim_cur = PyLong_AsLong(py_soft); + if (new.rlim_cur == (rlim_t) - 1 && PyErr_Occurred()) + return NULL; + new.rlim_max = PyLong_AsLong(py_hard); + if (new.rlim_max == (rlim_t) - 1 && PyErr_Occurred()) + return NULL; +#endif + newp = &new; + ret = sysctl(name, 5, NULL, 0, newp, sizeof(*newp)); + if (ret == -1) + return PyErr_SetFromErrno(PyExc_OSError); + Py_RETURN_NONE; +} diff --git a/psutil/arch/freebsd/specific.h b/psutil/arch/freebsd/specific.h index 875c8166..61c3f07b 100644 --- a/psutil/arch/freebsd/specific.h +++ b/psutil/arch/freebsd/specific.h @@ -24,6 +24,8 @@ PyObject* psutil_proc_memory_maps(PyObject* self, PyObject* args); PyObject* psutil_proc_num_fds(PyObject* self, PyObject* args); PyObject* psutil_proc_num_threads(PyObject* self, PyObject* args); PyObject* psutil_proc_threads(PyObject* self, PyObject* args); +PyObject* psutil_proc_getrlimit(PyObject* self, PyObject* args); +PyObject* psutil_proc_setrlimit(PyObject* self, PyObject* args); PyObject* psutil_swap_mem(PyObject* self, PyObject* args); PyObject* psutil_virtual_mem(PyObject* self, PyObject* args); PyObject* psutil_cpu_stats(PyObject* self, PyObject* args); diff --git a/psutil/tests/test_bsd.py b/psutil/tests/test_bsd.py index c91ee3a5..06a65087 100755 --- a/psutil/tests/test_bsd.py +++ b/psutil/tests/test_bsd.py @@ -474,6 +474,7 @@ class FreeBSDSystemTestCase(PsutilTestCase): psutil.sensors_temperatures()["coretemp"][cpu].high, sysctl_result) + # ===================================================================== # --- OpenBSD # ===================================================================== diff --git a/psutil/tests/test_contracts.py b/psutil/tests/test_contracts.py index 2d9e5917..39a52569 100755 --- a/psutil/tests/test_contracts.py +++ b/psutil/tests/test_contracts.py @@ -89,25 +89,29 @@ class TestAvailConstantsAPIs(PsutilTestCase): @unittest.skipIf(GITHUB_WHEELS, "not exposed via GITHUB_WHEELS") def test_linux_rlimit(self): ae = self.assertEqual - ae(hasattr(psutil, "RLIM_INFINITY"), LINUX) - ae(hasattr(psutil, "RLIMIT_AS"), LINUX) - ae(hasattr(psutil, "RLIMIT_CORE"), LINUX) - ae(hasattr(psutil, "RLIMIT_CPU"), LINUX) - ae(hasattr(psutil, "RLIMIT_DATA"), LINUX) - ae(hasattr(psutil, "RLIMIT_FSIZE"), LINUX) - ae(hasattr(psutil, "RLIMIT_LOCKS"), LINUX) - ae(hasattr(psutil, "RLIMIT_MEMLOCK"), LINUX) - ae(hasattr(psutil, "RLIMIT_NOFILE"), LINUX) - ae(hasattr(psutil, "RLIMIT_NPROC"), LINUX) - ae(hasattr(psutil, "RLIMIT_RSS"), LINUX) - ae(hasattr(psutil, "RLIMIT_STACK"), LINUX) + ae(hasattr(psutil, "RLIM_INFINITY"), LINUX or FREEBSD) + ae(hasattr(psutil, "RLIMIT_AS"), LINUX or FREEBSD) + ae(hasattr(psutil, "RLIMIT_CORE"), LINUX or FREEBSD) + ae(hasattr(psutil, "RLIMIT_CPU"), LINUX or FREEBSD) + ae(hasattr(psutil, "RLIMIT_DATA"), LINUX or FREEBSD) + ae(hasattr(psutil, "RLIMIT_FSIZE"), LINUX or FREEBSD) + ae(hasattr(psutil, "RLIMIT_MEMLOCK"), LINUX or FREEBSD) + ae(hasattr(psutil, "RLIMIT_NOFILE"), LINUX or FREEBSD) + ae(hasattr(psutil, "RLIMIT_NPROC"), LINUX or FREEBSD) + ae(hasattr(psutil, "RLIMIT_RSS"), LINUX or FREEBSD) + ae(hasattr(psutil, "RLIMIT_STACK"), LINUX or FREEBSD) + ae(hasattr(psutil, "RLIMIT_LOCKS"), LINUX) ae(hasattr(psutil, "RLIMIT_MSGQUEUE"), LINUX) # requires Linux 2.6.8 ae(hasattr(psutil, "RLIMIT_NICE"), LINUX) # requires Linux 2.6.12 ae(hasattr(psutil, "RLIMIT_RTPRIO"), LINUX) # requires Linux 2.6.12 ae(hasattr(psutil, "RLIMIT_RTTIME"), LINUX) # requires Linux 2.6.25 ae(hasattr(psutil, "RLIMIT_SIGPENDING"), LINUX) # requires Linux 2.6.8 + ae(hasattr(psutil, "RLIMIT_SWAP"), FREEBSD) + ae(hasattr(psutil, "RLIMIT_SBSIZE"), FREEBSD) + ae(hasattr(psutil, "RLIMIT_NPTS"), FREEBSD) + class TestAvailSystemAPIs(PsutilTestCase): @@ -155,7 +159,7 @@ class TestAvailProcessAPIs(PsutilTestCase): @unittest.skipIf(GITHUB_WHEELS, "not exposed via GITHUB_WHEELS") def test_rlimit(self): # requires Linux 2.6.36 - self.assertEqual(hasattr(psutil.Process, "rlimit"), LINUX) + self.assertEqual(hasattr(psutil.Process, "rlimit"), LINUX or FREEBSD) def test_io_counters(self): hasit = hasattr(psutil.Process, "io_counters") diff --git a/psutil/tests/test_process.py b/psutil/tests/test_process.py index b2328ba2..0d63979b 100755 --- a/psutil/tests/test_process.py +++ b/psutil/tests/test_process.py @@ -448,8 +448,9 @@ class TestProcess(PsutilTestCase): self.assertEqual(p.rlimit(psutil.RLIMIT_NOFILE), (5, 5)) # If pid is 0 prlimit() applies to the calling process and # we don't want that. - with self.assertRaises(ValueError): - psutil._psplatform.Process(0).rlimit(0) + if LINUX: + with self.assertRaisesRegex(ValueError, "can't use prlimit"): + psutil._psplatform.Process(0).rlimit(0) with self.assertRaises(ValueError): p.rlimit(psutil.RLIMIT_NOFILE, (5, 5, 5)) diff --git a/scripts/procinfo.py b/scripts/procinfo.py index f0605386..8eea3377 100755 --- a/scripts/procinfo.py +++ b/scripts/procinfo.py @@ -108,11 +108,14 @@ RLIMITS_MAP = { "RLIMIT_NICE": "nice", "RLIMIT_NOFILE": "openfiles", "RLIMIT_NPROC": "maxprocesses", + "RLIMIT_NPTS": "pseudoterms", "RLIMIT_RSS": "rss", "RLIMIT_RTPRIO": "realtimeprio", "RLIMIT_RTTIME": "rtimesched", + "RLIMIT_SBSIZE": "sockbufsize", "RLIMIT_SIGPENDING": "sigspending", "RLIMIT_STACK": "stack", + "RLIMIT_SWAP": "swapuse", } @@ -317,7 +320,7 @@ def run(pid, verbose=False): def main(argv=None): parser = argparse.ArgumentParser( description="print information about a process") - parser.add_argument("pid", type=int, help="process pid") + parser.add_argument("pid", type=int, help="process pid", nargs='?') parser.add_argument('--verbose', '-v', action='store_true', help="print more info") args = parser.parse_args() |