From 28855b4c4fbf0e10ed51a0f4e30f08ec83e524b9de569a777b70aa3ec6048e0f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mark=C3=A9ta=20Machov=C3=A1?= Date: Wed, 23 Aug 2023 11:06:16 +0000 Subject: [PATCH] Accepting request 1105452 from home:aplanas:branches:devel:languages:python - Add logind_y2038.patch to use logind if systemd >= 254 is used, to fix the issue of ut_tv.tv_sec and the Y2038 problem. OBS-URL: https://build.opensuse.org/request/show/1105452 OBS-URL: https://build.opensuse.org/package/show/devel:languages:python/python-psutil?expand=0&rev=158 --- logind_y2038.patch | 233 +++++++++++++++++++++++++++++ python-psutil.changes | 6 + python-psutil.spec | 4 + skip_rlimit_tests_on_python2.patch | 18 ++- 4 files changed, 253 insertions(+), 8 deletions(-) create mode 100644 logind_y2038.patch diff --git a/logind_y2038.patch b/logind_y2038.patch new file mode 100644 index 0000000..dca7e2b --- /dev/null +++ b/logind_y2038.patch @@ -0,0 +1,233 @@ +From 89b2d1896ffa8e5c9a8d9b89c3af0bb9027ce23b Mon Sep 17 00:00:00 2001 +From: Alberto Planas +Date: Tue, 22 Aug 2023 15:54:09 +0200 +Subject: [PATCH] Use logind instead of utmp because of Y2038 + +Bi-arch systems line x86-64 present the Y2038 problem, where an overflow +can be produced because some glibc compatibility decissions (see +https://github.com/thkukuk/utmpx/blob/main/Y2038.md for more +information) + +This patch uses logind from systemd instead of utmp on Linux systems, if +the systemd version is support the new API (>= 254). + +Signed-off-by: Alberto Planas +--- + INSTALL.rst | 4 +-- + psutil/_psutil_linux.c | 81 ++++++++++++++++++++++++++++++++++++++++-- + setup.py | 22 ++++++++++++ + 3 files changed, 102 insertions(+), 5 deletions(-) + +Index: psutil-5.9.5/INSTALL.rst +=================================================================== +--- psutil-5.9.5.orig/INSTALL.rst ++++ psutil-5.9.5/INSTALL.rst +@@ -17,12 +17,12 @@ Linux (build) + + Ubuntu / Debian:: + +- sudo apt-get install gcc python3-dev ++ sudo apt-get install gcc python3-dev libsystemd-dev + pip install --no-binary :all: psutil + + RedHat / CentOS:: + +- sudo yum install gcc python3-devel ++ sudo yum install gcc python3-devel systemd-devel + pip install --no-binary :all: psutil + + Alpine:: +Index: psutil-5.9.5/psutil/_psutil_linux.c +=================================================================== +--- psutil-5.9.5.orig/psutil/_psutil_linux.c ++++ psutil-5.9.5/psutil/_psutil_linux.c +@@ -14,7 +14,11 @@ + #include + #include + #include +-#include ++#ifdef SYSTEMD_LINUX ++ #include ++#else ++ #include ++#endif + #include + #include + #include +@@ -363,42 +367,102 @@ psutil_proc_cpu_affinity_set(PyObject *s + */ + static PyObject * + psutil_users(PyObject *self, PyObject *args) { ++#ifdef SYSTEMD_LINUX ++ char **sessions_list = NULL; ++#else + struct utmp *ut; ++#endif + PyObject *py_retlist = PyList_New(0); + PyObject *py_tuple = NULL; + PyObject *py_username = NULL; + PyObject *py_tty = NULL; + PyObject *py_hostname = NULL; + PyObject *py_user_proc = NULL; ++ double tstamp = 0.0; ++ pid_t pid = 0; + + if (py_retlist == NULL) + return NULL; ++#ifdef SYSTEMD_LINUX ++ int sessions = sd_get_sessions(&sessions_list); ++ for (int i = 0; i < sessions; i++) { ++ const char *session_id = sessions_list[i]; ++#else + setutent(); + while (NULL != (ut = getutent())) { ++#endif + py_tuple = NULL; + py_user_proc = NULL; ++ #ifdef SYSTEMD_LINUX ++ py_user_proc = Py_True; ++ #else + if (ut->ut_type == USER_PROCESS) + py_user_proc = Py_True; + else + py_user_proc = Py_False; ++ #endif ++ ++ #ifdef SYSTEMD_LINUX ++ char *username = NULL; ++ if (sd_session_get_username(session_id, &username) < 0) ++ goto error; ++ py_username = PyUnicode_DecodeFSDefault(username); ++ free(username); ++ #else + py_username = PyUnicode_DecodeFSDefault(ut->ut_user); ++ #endif + if (! py_username) + goto error; ++ ++ #ifdef SYSTEMD_LINUX ++ char *tty = NULL; ++ if (sd_session_get_tty(session_id, &tty) < 0) { ++ py_tty = PyUnicode_DecodeFSDefault("n/a"); ++ } else { ++ py_tty = PyUnicode_DecodeFSDefault(tty); ++ free(tty); ++ } ++ #else + py_tty = PyUnicode_DecodeFSDefault(ut->ut_line); ++ #endif + if (! py_tty) + goto error; ++ #ifdef SYSTEMD_LINUX ++ char *hostname = NULL; ++ if (sd_session_get_remote_host(session_id, &hostname) < 0) ++ goto error; ++ py_hostname = PyUnicode_DecodeFSDefault(hostname); ++ free(hostname); ++ #else + py_hostname = PyUnicode_DecodeFSDefault(ut->ut_host); ++ #endif + if (! py_hostname) + goto error; + ++ #ifdef SYSTEMD_LINUX ++ uint64_t usec = 0; ++ if (sd_session_get_start_time(session_id, &usec) < 0) ++ goto error; ++ tstamp = (double)usec / 1000000.0; ++ #else ++ tstamp = (double)ut->ut_tv.tv_sec; ++ #endif ++ ++ #ifdef SYSTEMD_LINUX ++ if (sd_session_get_leader(session_id, &pid) < 0) ++ goto error; ++ #else ++ pid = ut->ut_pid; ++ #endif ++ + py_tuple = Py_BuildValue( + "OOOdO" _Py_PARSE_PID, + py_username, // username + py_tty, // tty + py_hostname, // hostname +- (double)ut->ut_tv.tv_sec, // tstamp ++ tstamp, // tstamp + py_user_proc, // (bool) user process +- ut->ut_pid // process id ++ pid // process id + ); + if (! py_tuple) + goto error; +@@ -408,8 +472,15 @@ psutil_users(PyObject *self, PyObject *a + Py_CLEAR(py_tty); + Py_CLEAR(py_hostname); + Py_CLEAR(py_tuple); ++ #ifdef SYSTEMD_LINUX ++ free (sessions_list[i]); ++ #endif + } ++#ifdef SYSTEMD_LINUX ++ free(sessions_list); ++#else + endutent(); ++#endif + return py_retlist; + + error: +@@ -418,7 +489,11 @@ error: + Py_XDECREF(py_hostname); + Py_XDECREF(py_tuple); + Py_DECREF(py_retlist); ++#ifdef SYSTEMD_LINUX ++ free(sessions_list); ++#else + endutent(); ++#endif + return NULL; + } + +Index: psutil-5.9.5/setup.py +=================================================================== +--- psutil-5.9.5.orig/setup.py ++++ psutil-5.9.5/setup.py +@@ -184,6 +184,20 @@ def unix_can_compile(c_code): + shutil.rmtree(tempdir) + + ++def get_systemd_version(): ++ r = subprocess.run(["systemctl", "--version"], capture_output=True) ++ if r.returncode != 0: ++ return 0 ++ out = r.stdout.split() ++ if len(out) < 2: ++ return 0 ++ version = out[1] ++ try: ++ return int(version) ++ except ValueError: ++ return 0 ++ ++ + if WINDOWS: + def get_winver(): + maj, min = sys.getwindowsversion()[0:2] +@@ -302,10 +316,18 @@ elif LINUX: + if not unix_can_compile("#include "): + macros.append(("PSUTIL_ETHTOOL_MISSING_TYPES", 1)) + ++ libraries = [] ++ # Systemd >= 254 can replace utmp. See: ++ # https://github.com/thkukuk/utmpx/blob/main/utmp-to-logind.md ++ if get_systemd_version() >= 254: ++ macros.append(("SYSTEMD_LINUX", 1)) ++ libraries.append("systemd") ++ + macros.append(("PSUTIL_LINUX", 1)) + ext = Extension( + 'psutil._psutil_linux', + sources=sources + ['psutil/_psutil_linux.c'], ++ libraries=libraries, + define_macros=macros, + **py_limited_api) + diff --git a/python-psutil.changes b/python-psutil.changes index b635c94..40ed0ff 100644 --- a/python-psutil.changes +++ b/python-psutil.changes @@ -1,3 +1,9 @@ +------------------------------------------------------------------- +Wed Aug 23 09:40:44 UTC 2023 - Alberto Planas Dominguez + +- Add logind_y2038.patch to use logind if systemd >= 254 is used, to + fix the issue of ut_tv.tv_sec and the Y2038 problem. + ------------------------------------------------------------------- Wed May 3 09:04:54 UTC 2023 - Dirk Müller diff --git a/python-psutil.spec b/python-psutil.spec index 2547a8c..37cad1c 100644 --- a/python-psutil.spec +++ b/python-psutil.spec @@ -38,11 +38,15 @@ Patch2: skip_failing_tests.patch Patch3: skip_rlimit_tests_on_python2.patch # PATCH-FIX-SLE adopt change of used memory of procps Patch4: mem-used-bsc1181475.patch +# PATCH-FIX-UPSTREAM logind_y2038.patch gh#giampaolo/psutil#2300 aplanas@suse.com +Patch5: logind_y2038.patch BuildRequires: %{python_module devel} BuildRequires: %{python_module setuptools} BuildRequires: fdupes BuildRequires: python-rpm-macros Requires: procps +BuildRequires: systemd +BuildRequires: systemd-devel %if %{with test} BuildRequires: net-tools BuildRequires: procps diff --git a/skip_rlimit_tests_on_python2.patch b/skip_rlimit_tests_on_python2.patch index d45ea9c..4d79277 100644 --- a/skip_rlimit_tests_on_python2.patch +++ b/skip_rlimit_tests_on_python2.patch @@ -2,9 +2,11 @@ psutil/tests/test_process.py | 6 ++++++ 1 file changed, 6 insertions(+) ---- a/psutil/tests/test_process.py -+++ b/psutil/tests/test_process.py -@@ -416,6 +416,7 @@ class TestProcess(PsutilTestCase): +Index: psutil-5.9.5/psutil/tests/test_process.py +=================================================================== +--- psutil-5.9.5.orig/psutil/tests/test_process.py ++++ psutil-5.9.5/psutil/tests/test_process.py +@@ -419,6 +419,7 @@ class TestProcess(PsutilTestCase): p.ionice(init) @unittest.skipIf(not HAS_RLIMIT, "not supported") @@ -12,7 +14,7 @@ def test_rlimit_get(self): import resource p = psutil.Process(os.getpid()) -@@ -439,6 +440,7 @@ class TestProcess(PsutilTestCase): +@@ -442,6 +443,7 @@ class TestProcess(PsutilTestCase): self.assertGreaterEqual(ret[1], -1) @unittest.skipIf(not HAS_RLIMIT, "not supported") @@ -20,7 +22,7 @@ def test_rlimit_set(self): p = self.spawn_psproc() p.rlimit(psutil.RLIMIT_NOFILE, (5, 5)) -@@ -452,6 +454,7 @@ class TestProcess(PsutilTestCase): +@@ -455,6 +457,7 @@ class TestProcess(PsutilTestCase): p.rlimit(psutil.RLIMIT_NOFILE, (5, 5, 5)) @unittest.skipIf(not HAS_RLIMIT, "not supported") @@ -28,7 +30,7 @@ def test_rlimit(self): p = psutil.Process() testfn = self.get_testfn() -@@ -472,6 +475,7 @@ class TestProcess(PsutilTestCase): +@@ -475,6 +478,7 @@ class TestProcess(PsutilTestCase): self.assertEqual(p.rlimit(psutil.RLIMIT_FSIZE), (soft, hard)) @unittest.skipIf(not HAS_RLIMIT, "not supported") @@ -36,7 +38,7 @@ def test_rlimit_infinity(self): # First set a limit, then re-set it by specifying INFINITY # and assume we overridden the previous limit. -@@ -487,6 +491,7 @@ class TestProcess(PsutilTestCase): +@@ -490,6 +494,7 @@ class TestProcess(PsutilTestCase): self.assertEqual(p.rlimit(psutil.RLIMIT_FSIZE), (soft, hard)) @unittest.skipIf(not HAS_RLIMIT, "not supported") @@ -44,7 +46,7 @@ def test_rlimit_infinity_value(self): # RLIMIT_FSIZE should be RLIM_INFINITY, which will be a really # big number on a platform with large file support. On these -@@ -1276,6 +1281,7 @@ class TestProcess(PsutilTestCase): +@@ -1320,6 +1325,7 @@ class TestProcess(PsutilTestCase): self.assertEqual(normcase(p.exe()), normcase(PYTHON_EXE)) @unittest.skipIf(not POSIX, 'POSIX only')