From 90b35e3ae85651d67a095205adc94aaa0a4ec98f Mon Sep 17 00:00:00 2001 From: Giampaolo Rodola Date: Tue, 11 Apr 2023 12:04:03 +0200 Subject: [POSIX] psutil.users() loses precision for "started" attribute #2225 (#2226) --- .github/workflows/issues.py | 2 +- HISTORY.rst | 2 ++ psutil/_psutil_aix.c | 4 ++-- psutil/_psutil_bsd.c | 4 ++-- psutil/_psutil_linux.c | 4 ++-- psutil/_psutil_osx.c | 4 ++-- psutil/_psutil_sunos.c | 4 ++-- psutil/tests/test_posix.py | 40 ++++++++++++++++++++++++++++++++++------ 8 files changed, 47 insertions(+), 17 deletions(-) diff --git a/.github/workflows/issues.py b/.github/workflows/issues.py index 06438b97..77a9bc96 100644 --- a/.github/workflows/issues.py +++ b/.github/workflows/issues.py @@ -59,7 +59,7 @@ LABELS_MAP = { "wsl": ["wsl"], "unix": [ "psposix", "_psutil_posix", "waitpid", "statvfs", "/dev/tty", - "/dev/pts", + "/dev/pts", "posix", ], "pypy": ["pypy"], # types diff --git a/HISTORY.rst b/HISTORY.rst index a86f56c4..ac50e897 100644 --- a/HISTORY.rst +++ b/HISTORY.rst @@ -23,6 +23,8 @@ argument. - 2216_, [Windows]: fix tests when running in a virtual environment (patch by Matthieu Darbois) +- 2225_, [POSIX]: `users()`_ loses precision for ``started`` attribute (off by + 1 minute). 5.9.4 ===== diff --git a/psutil/_psutil_aix.c b/psutil/_psutil_aix.c index f5c5cc66..8a1b8de9 100644 --- a/psutil/_psutil_aix.c +++ b/psutil/_psutil_aix.c @@ -497,11 +497,11 @@ psutil_users(PyObject *self, PyObject *args) { if (! py_hostname) goto error; py_tuple = Py_BuildValue( - "(OOOfOi)", + "(OOOdOi)", py_username, // username py_tty, // tty py_hostname, // hostname - (float)ut->ut_tv.tv_sec, // tstamp + (double)ut->ut_tv.tv_sec, // tstamp py_user_proc, // (bool) user process ut->ut_pid // process id ); diff --git a/psutil/_psutil_bsd.c b/psutil/_psutil_bsd.c index 1ffa7b00..c2de7c91 100644 --- a/psutil/_psutil_bsd.c +++ b/psutil/_psutil_bsd.c @@ -966,11 +966,11 @@ psutil_users(PyObject *self, PyObject *args) { if (! py_hostname) goto error; py_tuple = Py_BuildValue( - "(OOOfi)", + "(OOOdi)", py_username, // username py_tty, // tty py_hostname, // hostname - (float)ut.ut_time, // start time + (double)ut.ut_time, // start time #if defined(PSUTIL_OPENBSD) || (defined(__FreeBSD_version) && __FreeBSD_version < 900000) -1 // process id (set to None later) #else diff --git a/psutil/_psutil_linux.c b/psutil/_psutil_linux.c index 924fe702..a6ee6025 100644 --- a/psutil/_psutil_linux.c +++ b/psutil/_psutil_linux.c @@ -392,11 +392,11 @@ psutil_users(PyObject *self, PyObject *args) { goto error; py_tuple = Py_BuildValue( - "OOOfO" _Py_PARSE_PID, + "OOOdO" _Py_PARSE_PID, py_username, // username py_tty, // tty py_hostname, // hostname - (float)ut->ut_tv.tv_sec, // tstamp + (double)ut->ut_tv.tv_sec, // tstamp py_user_proc, // (bool) user process ut->ut_pid // process id ); diff --git a/psutil/_psutil_osx.c b/psutil/_psutil_osx.c index ab43871f..ed29b33b 100644 --- a/psutil/_psutil_osx.c +++ b/psutil/_psutil_osx.c @@ -1579,11 +1579,11 @@ psutil_users(PyObject *self, PyObject *args) { if (! py_hostname) goto error; py_tuple = Py_BuildValue( - "(OOOfi)", + "(OOOdi)", py_username, // username py_tty, // tty py_hostname, // hostname - (float)utx->ut_tv.tv_sec, // start time + (double)utx->ut_tv.tv_sec, // start time utx->ut_pid // process id ); if (!py_tuple) { diff --git a/psutil/_psutil_sunos.c b/psutil/_psutil_sunos.c index 84bf1c40..e2e7c018 100644 --- a/psutil/_psutil_sunos.c +++ b/psutil/_psutil_sunos.c @@ -647,11 +647,11 @@ psutil_users(PyObject *self, PyObject *args) { if (! py_hostname) goto error; py_tuple = Py_BuildValue( - "(OOOfOi)", + "(OOOdOi)", py_username, // username py_tty, // tty py_hostname, // hostname - (float)ut->ut_tv.tv_sec, // tstamp + (double)ut->ut_tv.tv_sec, // tstamp py_user_proc, // (bool) user process ut->ut_pid // process id ); diff --git a/psutil/tests/test_posix.py b/psutil/tests/test_posix.py index 0dc1dfda..a37899fd 100755 --- a/psutil/tests/test_posix.py +++ b/psutil/tests/test_posix.py @@ -23,7 +23,6 @@ from psutil import MACOS from psutil import OPENBSD from psutil import POSIX from psutil import SUNOS -from psutil.tests import CI_TESTING from psutil.tests import HAS_NET_IO_COUNTERS from psutil.tests import PYTHON_EXE from psutil.tests import PsutilTestCase @@ -334,19 +333,48 @@ class TestSystemAPIs(PsutilTestCase): "couldn't find %s nic in 'ifconfig -a' output\n%s" % ( nic, output)) - @unittest.skipIf(CI_TESTING and not psutil.users(), "unreliable on CI") + # @unittest.skipIf(CI_TESTING and not psutil.users(), "unreliable on CI") @retry_on_failure() def test_users(self): - out = sh("who") + out = sh("who -u") if not out.strip(): raise self.skipTest("no users on this system") lines = out.split('\n') users = [x.split()[0] for x in lines] terminals = [x.split()[1] for x in lines] self.assertEqual(len(users), len(psutil.users())) - for u in psutil.users(): - self.assertIn(u.name, users) - self.assertIn(u.terminal, terminals) + with self.subTest(psutil=psutil.users(), who=out): + for idx, u in enumerate(psutil.users()): + self.assertEqual(u.name, users[idx]) + self.assertEqual(u.terminal, terminals[idx]) + p = psutil.Process(u.pid) + # on macOS time is off by ~47 secs for some reason, but + # the next test against 'who' CLI succeeds + delta = 60 if MACOS else 1 + self.assertAlmostEqual(u.started, p.create_time(), delta=delta) + + @retry_on_failure() + def test_users_started(self): + out = sh("who -u") + if not out.strip(): + raise self.skipTest("no users on this system") + # '2023-04-11 09:31' (Linux) + started = re.findall(r"\d\d\d\d-\d\d-\d\d \d\d:\d\d", out) + if started: + tstamp = "%Y-%m-%d %H:%M" + else: + # 'Apr 10 22:27' (macOS) + started = re.findall(r"[A-Z][a-z][a-z] \d\d \d\d:\d\d", out) + if started: + tstamp = "%b %d %H:%M" + else: + raise ValueError( + "cannot interpret tstamp in who output\n%s" % (out)) + with self.subTest(psutil=psutil.users(), who=out): + for idx, u in enumerate(psutil.users()): + psutil_value = datetime.datetime.fromtimestamp( + u.started).strftime(tstamp) + self.assertEqual(psutil_value, started[idx]) def test_pid_exists_let_raise(self): # According to "man 2 kill" possible error values for kill -- cgit v1.2.1