https://github.com/python/cpython/commit/704c4c79e8485c20fb59cea1acec005f365a4fca
commit: 704c4c79e8485c20fb59cea1acec005f365a4fca
branch: 3.13
author: Victor Stinner <[email protected]>
committer: vstinner <[email protected]>
date: 2026-06-25T15:24:36Z
summary:

[3.13] gh-151929: Get uptime on BSD/macOS in pythoninfo (#152189) (#152197) 
(#152207)

[3.14] gh-151929: Get uptime on BSD/macOS in pythoninfo (#152189) (#152197)

gh-151929: Get uptime on BSD/macOS in pythoninfo (#152189)

* Check sysctlbyname() function and sys/sysctl.h header in
  configure.
* Add _testcapi.uptime_bsd() function.

(cherry picked from commit b6d89edc4a13a71734ae1f1e386122bf62d68ed8)
(cherry picked from commit d25cf02a71ee1a77cd672a49b3b660e650d5e7a8)

files:
M Lib/test/pythoninfo.py
M Modules/_testcapimodule.c
M configure
M configure.ac
M pyconfig.h.in

diff --git a/Lib/test/pythoninfo.py b/Lib/test/pythoninfo.py
index 51da9d79f1f602..7d94be57dce4ee 100644
--- a/Lib/test/pythoninfo.py
+++ b/Lib/test/pythoninfo.py
@@ -1062,6 +1062,18 @@ def uptime_linux():
         return
 
 
+def uptime_bsd():
+    # Get sysctlbyname("kern.boottime")
+    try:
+        import _testcapi
+    except ImportError:
+        return None
+    try:
+        return _testcapi.uptime_bsd()
+    except (AttributeError, OSError):
+        return None
+
+
 def uptime_windows():
     try:
         import _winapi
@@ -1072,7 +1084,7 @@ def uptime_windows():
 
 
 def get_uptime():
-    for func in (uptime_boottime, uptime_linux, uptime_windows):
+    for func in (uptime_boottime, uptime_linux, uptime_bsd, uptime_windows):
         uptime = func()
         if uptime is not None:
             return uptime
@@ -1086,9 +1098,15 @@ def get_machine_id():
         if machine_guid:
             return machine_guid
 
-    machine_id = read_first_line("/etc/machine-id")
-    if machine_id:
-        return machine_id
+    for filename in (
+        # 
https://www.freedesktop.org/software/systemd/man/latest/machine-id.html
+        "/etc/machine-id",
+        # BSD
+        "/etc/hostid",
+    ):
+        machine_id = read_first_line(filename)
+        if machine_id:
+            return machine_id
 
     return None
 
@@ -1098,7 +1116,6 @@ def collect_linux(info_add):
     if boot_id:
         info_add('system.boot_id', boot_id)
 
-    # https://www.freedesktop.org/software/systemd/man/latest/machine-id.html
     machine_id = get_machine_id()
     if machine_id:
         info_add('system.machine_id', machine_id)
diff --git a/Modules/_testcapimodule.c b/Modules/_testcapimodule.c
index c18b9713b0c3fe..8bd662bc2944ce 100644
--- a/Modules/_testcapimodule.c
+++ b/Modules/_testcapimodule.c
@@ -22,6 +22,9 @@
 #ifdef HAVE_SYS_WAIT_H
 #  include <sys/wait.h>           // W_STOPCODE
 #endif
+#ifdef HAVE_SYS_SYSCTL_H
+#  include <sys/sysctl.h>         // sysctlbyname()
+#endif
 
 #ifdef bool
 #  error "The public headers should not include <stdbool.h>, see gh-48924"
@@ -3486,6 +3489,31 @@ toggle_reftrace_printer(PyObject *ob, PyObject *arg)
     Py_RETURN_NONE;
 }
 
+
+#ifdef HAVE_SYSCTLBYNAME
+static PyObject*
+uptime_bsd(PyObject *Py_UNUSED(self), PyObject *Py_UNUSED(args))
+{
+    struct timeval tv;
+    size_t size = sizeof(tv);
+    int res = sysctlbyname("kern.boottime", &tv, &size, NULL, 0);
+    if (res != 0) {
+        return PyErr_SetFromErrno(PyExc_OSError);
+    }
+    double boottime = (double)tv.tv_sec + tv.tv_usec * 1e-6;
+
+    PyTime_t now_t;
+    if (PyTime_Time(&now_t) < 0) {
+        return NULL;
+    }
+    double now = PyTime_AsSecondsDouble(now_t);
+
+    double uptime = now - boottime;
+    return PyFloat_FromDouble(uptime);
+}
+#endif
+
+
 static PyMethodDef TestMethods[] = {
     {"set_errno",               set_errno,                       METH_VARARGS},
     {"test_config",             test_config,                     METH_NOARGS},
@@ -3632,6 +3660,9 @@ static PyMethodDef TestMethods[] = {
     {"tracemalloc_track_race", tracemalloc_track_race, METH_NOARGS},
     {"toggle_reftrace_printer", toggle_reftrace_printer, METH_O},
     {"finalize_thread_hang", finalize_thread_hang, METH_O, NULL},
+#ifdef HAVE_SYSCTLBYNAME
+    {"uptime_bsd", uptime_bsd, METH_NOARGS},
+#endif
     {NULL, NULL} /* sentinel */
 };
 
diff --git a/configure b/configure
index 0df47513085d5e..4f318effde14ab 100755
--- a/configure
+++ b/configure
@@ -11154,6 +11154,12 @@ if test "x$ac_cv_header_sys_syscall_h" = xyes
 then :
   printf "%s\n" "#define HAVE_SYS_SYSCALL_H 1" >>confdefs.h
 
+fi
+ac_fn_c_check_header_compile "$LINENO" "sys/sysctl.h" 
"ac_cv_header_sys_sysctl_h" "$ac_includes_default"
+if test "x$ac_cv_header_sys_sysctl_h" = xyes
+then :
+  printf "%s\n" "#define HAVE_SYS_SYSCTL_H 1" >>confdefs.h
+
 fi
 ac_fn_c_check_header_compile "$LINENO" "sys/sysmacros.h" 
"ac_cv_header_sys_sysmacros_h" "$ac_includes_default"
 if test "x$ac_cv_header_sys_sysmacros_h" = xyes
@@ -19185,6 +19191,12 @@ if test "x$ac_cv_func_sysconf" = xyes
 then :
   printf "%s\n" "#define HAVE_SYSCONF 1" >>confdefs.h
 
+fi
+ac_fn_c_check_func "$LINENO" "sysctlbyname" "ac_cv_func_sysctlbyname"
+if test "x$ac_cv_func_sysctlbyname" = xyes
+then :
+  printf "%s\n" "#define HAVE_SYSCTLBYNAME 1" >>confdefs.h
+
 fi
 ac_fn_c_check_func "$LINENO" "tcgetpgrp" "ac_cv_func_tcgetpgrp"
 if test "x$ac_cv_func_tcgetpgrp" = xyes
diff --git a/configure.ac b/configure.ac
index a016a439c6c8ed..2b98b0fc594b9e 100644
--- a/configure.ac
+++ b/configure.ac
@@ -3033,7 +3033,8 @@ AC_CHECK_HEADERS([ \
   sys/endian.h sys/epoll.h sys/event.h sys/eventfd.h sys/file.h sys/ioctl.h 
sys/kern_control.h \
   sys/loadavg.h sys/lock.h sys/memfd.h sys/mkdev.h sys/mman.h sys/modem.h 
sys/param.h sys/pidfd.h sys/poll.h \
   sys/random.h sys/resource.h sys/select.h sys/sendfile.h sys/socket.h 
sys/soundcard.h sys/stat.h \
-  sys/statvfs.h sys/sys_domain.h sys/syscall.h sys/sysmacros.h sys/termio.h 
sys/time.h sys/times.h sys/timerfd.h \
+  sys/statvfs.h sys/sys_domain.h sys/syscall.h sys/sysctl.h \
+  sys/sysmacros.h sys/termio.h sys/time.h sys/times.h sys/timerfd.h \
   sys/types.h sys/uio.h sys/un.h sys/utsname.h sys/wait.h sys/xattr.h 
sysexits.h syslog.h \
   termios.h util.h utime.h utmp.h \
 ])
@@ -5263,7 +5264,7 @@ AC_CHECK_FUNCS([ \
   setresuid setreuid setsid setuid setvbuf shutdown sigaction sigaltstack \
   sigfillset siginterrupt sigpending sigrelse sigtimedwait sigwait \
   sigwaitinfo snprintf splice strftime strlcpy strsignal symlinkat sync \
-  sysconf tcgetpgrp tcsetpgrp tempnam timegm times tmpfile \
+  sysconf sysctlbyname tcgetpgrp tcsetpgrp tempnam timegm times tmpfile \
   tmpnam tmpnam_r truncate ttyname_r umask uname unlinkat unlockpt utimensat 
utimes vfork \
   wait wait3 wait4 waitid waitpid wcscoll wcsftime wcsxfrm wmemcmp writev \
 ])
diff --git a/pyconfig.h.in b/pyconfig.h.in
index e18a6426b068c2..85ce754fd3ffbf 100644
--- a/pyconfig.h.in
+++ b/pyconfig.h.in
@@ -1324,6 +1324,9 @@
 /* Define to 1 if you have the `sysconf' function. */
 #undef HAVE_SYSCONF
 
+/* Define to 1 if you have the `sysctlbyname' function. */
+#undef HAVE_SYSCTLBYNAME
+
 /* Define to 1 if you have the <sysexits.h> header file. */
 #undef HAVE_SYSEXITS_H
 
@@ -1428,6 +1431,9 @@
 /* Define to 1 if you have the <sys/syscall.h> header file. */
 #undef HAVE_SYS_SYSCALL_H
 
+/* Define to 1 if you have the <sys/sysctl.h> header file. */
+#undef HAVE_SYS_SYSCTL_H
+
 /* Define to 1 if you have the <sys/sysmacros.h> header file. */
 #undef HAVE_SYS_SYSMACROS_H
 

_______________________________________________
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3//lists/python-checkins.python.org
Member address: [email protected]

Reply via email to