diff options
author | Giampaolo Rodola <g.rodola@gmail.com> | 2021-01-15 19:07:38 +0100 |
---|---|---|
committer | Giampaolo Rodola <g.rodola@gmail.com> | 2021-01-15 19:07:38 +0100 |
commit | 4ad3380bb312b6ea06717e3adc1f60ac8daf4a05 (patch) | |
tree | 923f2b548ada7533fb6e794b8253941ec225b6f6 | |
parent | 3223228b0558e42508cf9f8cce84d89c79b5c52b (diff) | |
parent | e80cabe5206fd7ef14fd6a47e2571f660f95babf (diff) | |
download | psutil-new-cpu-count.tar.gz |
Merge branch 'master' into new-cpu-countnew-cpu-count
-rw-r--r-- | .github/workflows/issues.py | 17 | ||||
-rw-r--r-- | CREDITS | 9 | ||||
-rw-r--r-- | HISTORY.rst | 10 | ||||
-rw-r--r-- | README.rst | 9 | ||||
-rw-r--r-- | docs/DEVNOTES | 6 | ||||
-rw-r--r-- | docs/index.rst | 23 | ||||
-rw-r--r-- | psutil/_pslinux.py | 52 | ||||
-rw-r--r-- | psutil/_psutil_common.c | 3 | ||||
-rw-r--r-- | psutil/_psutil_osx.c | 16 | ||||
-rw-r--r-- | psutil/_psutil_windows.c | 29 | ||||
-rw-r--r-- | psutil/arch/osx/process_info.c | 13 | ||||
-rw-r--r-- | psutil/arch/windows/wmi.c | 26 | ||||
-rwxr-xr-x | psutil/tests/test_linux.py | 4 |
13 files changed, 93 insertions, 124 deletions
diff --git a/.github/workflows/issues.py b/.github/workflows/issues.py index 91e12202..964e5192 100644 --- a/.github/workflows/issues.py +++ b/.github/workflows/issues.py @@ -180,14 +180,6 @@ def is_event_new_pr(): return False -def is_event_new_comment(): - data = _get_event_data() - try: - return data['action'] == 'created' and 'comment' in data - except KeyError: - return False - - def get_issue(): data = _get_event_data() try: @@ -317,10 +309,6 @@ def on_new_pr(issue): # issue.create_comment(REPLY_UPDATE_CHANGELOG) -def on_new_comment(issue): - pass - - def main(): issue = get_issue() stype = "PR" if is_pr(issue) else "issue" @@ -336,11 +324,8 @@ def main(): add_labels_from_text(issue, issue.title) add_labels_from_new_body(issue, issue.body) on_new_pr(issue) - elif is_event_new_comment(): - log("created new comment for %s" % issue) - on_new_comment(issue) else: - raise ValueError("unhandled event") + log("unhandled event") if __name__ == '__main__': @@ -95,6 +95,9 @@ I: 557 Donations ------------------------------------------------------------------------------- +N: aristocratos +W: https://github.com/aristocratos + N: Daniel Widdis C: Washington, USA W: https://github.com/dbwiddis @@ -542,7 +545,7 @@ I: 1042, 1079, 1070 N: Oleksii Shevchuk W: https://github.com/alxchk -I: 1077, 1093, 1091, 1220, 1346 +I: 1077, 1093, 1091, 1220, 1346, 1904 N: Prodesire W: https://github.com/Prodesire @@ -729,3 +732,7 @@ I: 1620, 1727 N: Tim Schlueter W: https://github.com/modelrockettier I: 1822 + +N: marxin +W: https://github.com/marxin +I: 1851 diff --git a/HISTORY.rst b/HISTORY.rst index 9f5281f9..dc4afbff 100644 --- a/HISTORY.rst +++ b/HISTORY.rst @@ -5,11 +5,21 @@ XXXX-XX-XX +**Enhancements** + +- 1851_: [Linux] cpu_freq() is slow on systems with many CPUs. Read current + frequency values for all CPUs from /proc/cpuinfo instead of opening many + files in /sys fs. (patch by marxin) + **Bug fixes** - 1456_: [macOS] psutil.cpu_freq()'s min and max are set to 0 if can't be determined (instead of crashing). +- 1512_: [macOS] sometimes Process.connections() will crash with EOPNOTSUPP + for one connection; this is now ignored. - 1892_: [macOS] psutil.cpu_freq() broken on Apple M1. +- 1904_: [Windows] OpenProcess fails with ERROR_SUCCESS due to GetLastError() + called after sprintf(). (patch by alxchk) 5.8.0 ===== @@ -23,7 +23,7 @@ :alt: Code quality .. |github-actions| image:: https://img.shields.io/github/workflow/status/giampaolo/psutil/CI?label=Linux%2C%20macOS%2C%20FreeBSD - :target: https://github.com/giampaolo/psutil/actions?query=workflow%3ACI + :target: https://github.com/giampaolo/psutil/actions?query=workflow%3Abuild :alt: Linux, macOS, Windows tests .. |appveyor| image:: https://img.shields.io/appveyor/ci/giampaolo/psutil/master.svg?maxAge=3600&label=Windows @@ -35,7 +35,7 @@ :alt: Test coverage (coverall.io) .. |doc| image:: https://readthedocs.org/projects/psutil/badge/?version=latest - :target: http://psutil.readthedocs.io/en/latest/?badge=latest + :target: https://psutil.readthedocs.io/en/latest/ :alt: Documentation Status .. |version| image:: https://img.shields.io/pypi/v/psutil.svg?label=pypi @@ -43,7 +43,6 @@ :alt: Latest version .. |py-versions| image:: https://img.shields.io/pypi/pyversions/psutil.svg - :target: https://pypi.org/project/psutil :alt: Supported Python versions .. |packages| image:: https://repology.org/badge/tiny-repos/python:psutil.svg @@ -133,10 +132,12 @@ Supporters .. raw:: html <div> - <a href="https://github.com/dbwiddis"><img height="40" width="40" src="https://avatars1.githubusercontent.com/u/9291703?s=88&u=3a4cbf1ea36068a36392856adb2fb02f623a3235&v=4" /></a> + <a href="https://github.com/dbwiddis"><img height="40" width="40" title="Daniel Widdis" src="https://avatars1.githubusercontent.com/u/9291703?s=88&v=4" /></a> + <a href="https://github.com/aristocratos"><img height="40" width="40" title="aristocratos" src="https://avatars3.githubusercontent.com/u/59659483?s=96&v=4" /></a> </div> <sup><a href="https://github.com/sponsors/giampaolo">add your avatar</a></sup> + Contributing ============ diff --git a/docs/DEVNOTES b/docs/DEVNOTES index 7fe14f7d..915754d6 100644 --- a/docs/DEVNOTES +++ b/docs/DEVNOTES @@ -34,18 +34,12 @@ FEATURES - #772: extended net_io_counters() metrics. -- #900: wheels for macOS and Linux. - - #922: extended net_io_stats() info. - #914: extended platform specific process info. - #898: wifi stats -- #893: (BSD) process environ - -- #809: (BSD) per-process resource limits (rlimit()). - - (UNIX) process root (different from cwd) - #782: (UNIX) process num of signals received. diff --git a/docs/index.rst b/docs/index.rst index 612cafb8..595130cd 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -73,28 +73,21 @@ Sponsors Supporters ---------- -None yet. - .. raw:: html + <div> + <a href="https://github.com/dbwiddis"><img height="40" width="40" title="Daniel Widdis" src="https://avatars1.githubusercontent.com/u/9291703?s=88&v=4" /></a> + <a href="https://github.com/aristocratos"><img height="40" width="40" title="aristocratos" src="https://avatars3.githubusercontent.com/u/59659483?s=96&v=4" /></a> + </div> + <br /> <sup><a href="https://github.com/sponsors/giampaolo">add your avatar</a></sup> Install ======= -Linux Ubuntu / Debian:: - - sudo apt-get install gcc python3-dev - sudo pip3 install psutil - -Linux Redhat:: - - sudo yum install gcc python3-devel - sudo pip3 install psutil - -Windows:: +On Linux, Windows, macOS:: - pip3 install psutil + pip install psutil For other platforms see more detailed `install <https://github.com/giampaolo/psutil/blob/master/INSTALL.rst>`_ @@ -2438,7 +2431,7 @@ Kill process tree timeout=None, on_terminate=None): """Kill a process tree (including grandchildren) with signal "sig" and return a (gone, still_alive) tuple. - "on_terminate", if specified, is a callabck function which is + "on_terminate", if specified, is a callback function which is called as soon as a child terminates. """ assert pid != os.getpid(), "won't kill myself" diff --git a/psutil/_pslinux.py b/psutil/_pslinux.py index 0cb8eaf3..69b175c5 100644 --- a/psutil/_pslinux.py +++ b/psutil/_pslinux.py @@ -736,6 +736,17 @@ def cpu_stats(): ctx_switches, interrupts, soft_interrupts, syscalls) +def _cpu_get_cpuinfo_freq(): + """Return current CPU frequency from cpuinfo if available. + """ + ret = [] + with open_binary('%s/cpuinfo' % get_procfs_path()) as f: + for line in f: + if line.lower().startswith(b'cpu mhz'): + ret.append(float(line.split(b':', 1)[1])) + return ret + + if os.path.exists("/sys/devices/system/cpu/cpufreq/policy0") or \ os.path.exists("/sys/devices/system/cpu/cpu0/cpufreq"): def cpu_freq(): @@ -743,20 +754,19 @@ if os.path.exists("/sys/devices/system/cpu/cpufreq/policy0") or \ Contrarily to other OSes, Linux updates these values in real-time. """ - def get_path(num): - for p in ("/sys/devices/system/cpu/cpufreq/policy%s" % num, - "/sys/devices/system/cpu/cpu%s/cpufreq" % num): - if os.path.exists(p): - return p - + cpuinfo_freqs = _cpu_get_cpuinfo_freq() + paths = sorted( + glob.glob("/sys/devices/system/cpu/cpufreq/policy[0-9]*") or + glob.glob("/sys/devices/system/cpu/cpu[0-9]*/cpufreq")) ret = [] - for n in range(cpu_count_logical()): - path = get_path(n) - if not path: - continue - - pjoin = os.path.join - curr = cat(pjoin(path, "scaling_cur_freq"), fallback=None) + pjoin = os.path.join + for i, path in enumerate(paths): + if len(paths) == len(cpuinfo_freqs): + # take cached value from cpuinfo if available, see: + # https://github.com/giampaolo/psutil/issues/1851 + curr = cpuinfo_freqs[i] + else: + curr = cat(pjoin(path, "scaling_cur_freq"), fallback=None) if curr is None: # Likely an old RedHat, see: # https://github.com/giampaolo/psutil/issues/1071 @@ -770,24 +780,12 @@ if os.path.exists("/sys/devices/system/cpu/cpufreq/policy0") or \ ret.append(_common.scpufreq(curr, min_, max_)) return ret -elif os.path.exists("/proc/cpuinfo"): +else: def cpu_freq(): """Alternate implementation using /proc/cpuinfo. min and max frequencies are not available and are set to None. """ - ret = [] - with open_binary('%s/cpuinfo' % get_procfs_path()) as f: - for line in f: - if line.lower().startswith(b'cpu mhz'): - key, value = line.split(b':', 1) - ret.append(_common.scpufreq(float(value), 0., 0.)) - return ret - -else: - def cpu_freq(): - """Dummy implementation when none of the above files are present. - """ - return [] + return [_common.scpufreq(x, 0., 0.) for x in _cpu_get_cpuinfo_freq()] # ===================================================================== diff --git a/psutil/_psutil_common.c b/psutil/_psutil_common.c index e9f86179..b82d5e89 100644 --- a/psutil/_psutil_common.c +++ b/psutil/_psutil_common.c @@ -83,8 +83,9 @@ PyErr_SetFromOSErrnoWithSyscall(const char *syscall) { char fullmsg[1024]; #ifdef PSUTIL_WINDOWS + DWORD dwLastError = GetLastError(); sprintf(fullmsg, "(originated from %s)", syscall); - PyErr_SetFromWindowsErrWithFilename(GetLastError(), fullmsg); + PyErr_SetFromWindowsErrWithFilename(dwLastError, fullmsg); #else PyObject *exc; sprintf(fullmsg, "%s (originated from %s)", strerror(errno), syscall); diff --git a/psutil/_psutil_osx.c b/psutil/_psutil_osx.c index 47b5393f..a12679ec 100644 --- a/psutil/_psutil_osx.c +++ b/psutil/_psutil_osx.c @@ -1027,9 +1027,18 @@ psutil_proc_connections(PyObject *self, PyObject *args) { PROC_PIDFDSOCKETINFO, &si, sizeof(si)); // --- errors checking - if ((nb <= 0) || (nb < sizeof(si))) { + if ((nb <= 0) || (nb < sizeof(si)) || (errno != 0)) { if (errno == EBADF) { // let's assume socket has been closed + psutil_debug("proc_pidfdinfo(PROC_PIDFDSOCKETINFO) -> " + "EBADF (ignored)"); + continue; + } + else if (errno == EOPNOTSUPP) { + // may happen sometimes, see: + // https://github.com/giampaolo/psutil/issues/1512 + psutil_debug("proc_pidfdinfo(PROC_PIDFDSOCKETINFO) -> " + "EOPNOTSUPP (ignored)"); continue; } else { @@ -1063,11 +1072,6 @@ psutil_proc_connections(PyObject *self, PyObject *args) { if (inseq == 0) continue; - if (errno != 0) { - PyErr_SetFromErrno(PyExc_OSError); - goto error; - } - if ((family == AF_INET) || (family == AF_INET6)) { if (family == AF_INET) { inet_ntop(AF_INET, diff --git a/psutil/_psutil_windows.c b/psutil/_psutil_windows.c index 1ac98a07..1b813f99 100644 --- a/psutil/_psutil_windows.c +++ b/psutil/_psutil_windows.c @@ -44,35 +44,6 @@ static PyObject *TimeoutAbandoned; /* - * Return the number of logical, active CPUs. Return 0 if undetermined. - * See discussion at: https://bugs.python.org/issue33166#msg314631 - */ -unsigned int -psutil_get_num_cpus(int fail_on_err) { - unsigned int ncpus = 0; - - // Minimum requirement: Windows 7 - if (GetActiveProcessorCount != NULL) { - ncpus = GetActiveProcessorCount(ALL_PROCESSOR_GROUPS); - if ((ncpus == 0) && (fail_on_err == 1)) { - PyErr_SetFromWindowsErr(0); - } - } - else { - psutil_debug("GetActiveProcessorCount() not available; " - "using GetSystemInfo()"); - ncpus = (unsigned int)PSUTIL_SYSTEM_INFO.dwNumberOfProcessors; - if ((ncpus <= 0) && (fail_on_err == 1)) { - PyErr_SetString( - PyExc_RuntimeError, - "GetSystemInfo() failed to retrieve CPU count"); - } - } - return ncpus; -} - - -/* * Return a Python float representing the system uptime expressed in seconds * since the epoch. */ diff --git a/psutil/arch/osx/process_info.c b/psutil/arch/osx/process_info.c index fb9f24ff..15ad3b89 100644 --- a/psutil/arch/osx/process_info.c +++ b/psutil/arch/osx/process_info.c @@ -370,14 +370,21 @@ psutil_get_kinfo_proc(pid_t pid, struct kinfo_proc *kp) { /* * A wrapper around proc_pidinfo(). + * https://opensource.apple.com/source/xnu/xnu-2050.7.9/bsd/kern/proc_info.c. * Returns 0 on failure (and Python exception gets already set). */ int psutil_proc_pidinfo(pid_t pid, int flavor, uint64_t arg, void *pti, int size) { errno = 0; - int ret = proc_pidinfo(pid, flavor, arg, pti, size); - if ((ret <= 0) || ((unsigned long)ret < sizeof(pti))) { - psutil_raise_for_pid(pid, "proc_pidinfo()"); + int ret; + + ret = proc_pidinfo(pid, flavor, arg, pti, size); + if (ret <= 0) { + psutil_raise_for_pid(pid, "proc_pidinfo() failed"); + return 0; + } + else if ((unsigned long )ret < sizeof(pti)) { + psutil_raise_for_pid(pid, "proc_pidinfo() len mismatch"); return 0; } return ret; diff --git a/psutil/arch/windows/wmi.c b/psutil/arch/windows/wmi.c index f9a847d3..5fad4053 100644 --- a/psutil/arch/windows/wmi.c +++ b/psutil/arch/windows/wmi.c @@ -64,22 +64,28 @@ psutil_init_loadavg_counter(PyObject *self, PyObject *args) { HANDLE event; HANDLE waitHandle; - if ((PdhOpenQueryW(NULL, 0, &hQuery)) != ERROR_SUCCESS) - goto error; + if ((PdhOpenQueryW(NULL, 0, &hQuery)) != ERROR_SUCCESS) { + PyErr_Format(PyExc_RuntimeError, "PdhOpenQueryW failed"); + return NULL; + } s = PdhAddEnglishCounterW(hQuery, szCounterPath, 0, &hCounter); - if (s != ERROR_SUCCESS) - goto error; + if (s != ERROR_SUCCESS) { + PyErr_Format(PyExc_RuntimeError, "PdhAddEnglishCounterW failed"); + return NULL; + } event = CreateEventW(NULL, FALSE, FALSE, L"LoadUpdateEvent"); if (event == NULL) { - PyErr_SetFromWindowsErr(0); + PyErr_SetFromOSErrnoWithSyscall("CreateEventW"); return NULL; } s = PdhCollectQueryDataEx(hQuery, SAMPLING_INTERVAL, event); - if (s != ERROR_SUCCESS) - goto error; + if (s != ERROR_SUCCESS) { + PyErr_Format(PyExc_RuntimeError, "PdhCollectQueryDataEx failed"); + return NULL; + } ret = RegisterWaitForSingleObject( &waitHandle, @@ -91,15 +97,11 @@ psutil_init_loadavg_counter(PyObject *self, PyObject *args) { WT_EXECUTEDEFAULT); if (ret == 0) { - PyErr_SetFromWindowsErr(0); + PyErr_SetFromOSErrnoWithSyscall("RegisterWaitForSingleObject"); return NULL; } Py_RETURN_NONE; - -error: - PyErr_SetFromWindowsErr(0); - return NULL; } diff --git a/psutil/tests/test_linux.py b/psutil/tests/test_linux.py index c6759ba0..e03490b3 100755 --- a/psutil/tests/test_linux.py +++ b/psutil/tests/test_linux.py @@ -794,18 +794,14 @@ class TestSystemCPUFrequency(PsutilTestCase): if path.startswith('/sys/devices/system/cpu/'): return False else: - if path == "/proc/cpuinfo": - flags.append(None) return os_path_exists(path) - flags = [] os_path_exists = os.path.exists try: with mock.patch("os.path.exists", side_effect=path_exists_mock): reload_module(psutil._pslinux) ret = psutil.cpu_freq() assert ret - assert flags self.assertEqual(ret.max, 0.0) self.assertEqual(ret.min, 0.0) for freq in psutil.cpu_freq(percpu=True): |