diff --git a/Lib/test/pythoninfo.py b/Lib/test/pythoninfo.py index 7f3d566e988d80..a2767f3975bed2 100644 --- a/Lib/test/pythoninfo.py +++ b/Lib/test/pythoninfo.py @@ -1083,6 +1083,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 @@ -1093,7 +1105,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 @@ -1107,9 +1119,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 @@ -1119,7 +1137,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 9c90d1fc36f398..799390c2705328 100644 --- a/Modules/_testcapimodule.c +++ b/Modules/_testcapimodule.c @@ -22,6 +22,9 @@ #ifdef HAVE_SYS_WAIT_H # include // W_STOPCODE #endif +#ifdef HAVE_SYS_SYSCTL_H +# include // sysctlbyname() +#endif #ifdef bool # error "The public headers should not include , see gh-48924" @@ -2970,6 +2973,31 @@ test_soft_deprecated_macros(PyObject *Py_UNUSED(self), PyObject *Py_UNUSED(args) 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}, @@ -3076,6 +3104,9 @@ static PyMethodDef TestMethods[] = { {"test_thread_state_ensure_detachment", test_thread_state_ensure_detachment, METH_NOARGS}, {"test_thread_state_ensure_detached_gilstate", test_thread_state_ensure_detached_gilstate, METH_NOARGS}, {"test_thread_state_release_with_destructor", test_thread_state_release_with_destructor, METH_NOARGS}, +#ifdef HAVE_SYSCTLBYNAME + {"uptime_bsd", uptime_bsd, METH_NOARGS}, +#endif {NULL, NULL} /* sentinel */ }; diff --git a/configure b/configure index a978b613514f12..e96b87989793a8 100755 --- a/configure +++ b/configure @@ -12104,6 +12104,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 @@ -21049,6 +21055,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 a2729c22386a95..cd1883f0195c47 100644 --- a/configure.ac +++ b/configure.ac @@ -3163,7 +3163,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 \ ]) @@ -5431,7 +5432,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 a84b74299e159b..a05cd8ecc91e19 100644 --- a/pyconfig.h.in +++ b/pyconfig.h.in @@ -1417,6 +1417,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 header file. */ #undef HAVE_SYSEXITS_H @@ -1521,6 +1524,9 @@ /* Define to 1 if you have the header file. */ #undef HAVE_SYS_SYSCALL_H +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_SYSCTL_H + /* Define to 1 if you have the header file. */ #undef HAVE_SYS_SYSMACROS_H