Skip to content

Commit d25cf02

Browse files
authored
[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 b6d89ed)
1 parent be65a38 commit d25cf02

5 files changed

Lines changed: 74 additions & 7 deletions

File tree

Lib/test/pythoninfo.py

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1064,6 +1064,18 @@ def uptime_linux():
10641064
return
10651065

10661066

1067+
def uptime_bsd():
1068+
# Get sysctlbyname("kern.boottime")
1069+
try:
1070+
import _testcapi
1071+
except ImportError:
1072+
return None
1073+
try:
1074+
return _testcapi.uptime_bsd()
1075+
except (AttributeError, OSError):
1076+
return None
1077+
1078+
10671079
def uptime_windows():
10681080
try:
10691081
import _winapi
@@ -1074,7 +1086,7 @@ def uptime_windows():
10741086

10751087

10761088
def get_uptime():
1077-
for func in (uptime_boottime, uptime_linux, uptime_windows):
1089+
for func in (uptime_boottime, uptime_linux, uptime_bsd, uptime_windows):
10781090
uptime = func()
10791091
if uptime is not None:
10801092
return uptime
@@ -1088,9 +1100,15 @@ def get_machine_id():
10881100
if machine_guid:
10891101
return machine_guid
10901102

1091-
machine_id = read_first_line("/etc/machine-id")
1092-
if machine_id:
1093-
return machine_id
1103+
for filename in (
1104+
# https://www.freedesktop.org/software/systemd/man/latest/machine-id.html
1105+
"/etc/machine-id",
1106+
# BSD
1107+
"/etc/hostid",
1108+
):
1109+
machine_id = read_first_line(filename)
1110+
if machine_id:
1111+
return machine_id
10941112

10951113
return None
10961114

@@ -1100,7 +1118,6 @@ def collect_linux(info_add):
11001118
if boot_id:
11011119
info_add('system.boot_id', boot_id)
11021120

1103-
# https://www.freedesktop.org/software/systemd/man/latest/machine-id.html
11041121
machine_id = get_machine_id()
11051122
if machine_id:
11061123
info_add('system.machine_id', machine_id)

Modules/_testcapimodule.c

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,9 @@
2222
#ifdef HAVE_SYS_WAIT_H
2323
# include <sys/wait.h> // W_STOPCODE
2424
#endif
25+
#ifdef HAVE_SYS_SYSCTL_H
26+
# include <sys/sysctl.h> // sysctlbyname()
27+
#endif
2528

2629
#ifdef bool
2730
# error "The public headers should not include <stdbool.h>, see gh-48924"
@@ -2568,6 +2571,31 @@ toggle_reftrace_printer(PyObject *ob, PyObject *arg)
25682571
Py_RETURN_NONE;
25692572
}
25702573

2574+
2575+
#ifdef HAVE_SYSCTLBYNAME
2576+
static PyObject*
2577+
uptime_bsd(PyObject *Py_UNUSED(self), PyObject *Py_UNUSED(args))
2578+
{
2579+
struct timeval tv;
2580+
size_t size = sizeof(tv);
2581+
int res = sysctlbyname("kern.boottime", &tv, &size, NULL, 0);
2582+
if (res != 0) {
2583+
return PyErr_SetFromErrno(PyExc_OSError);
2584+
}
2585+
double boottime = (double)tv.tv_sec + tv.tv_usec * 1e-6;
2586+
2587+
PyTime_t now_t;
2588+
if (PyTime_Time(&now_t) < 0) {
2589+
return NULL;
2590+
}
2591+
double now = PyTime_AsSecondsDouble(now_t);
2592+
2593+
double uptime = now - boottime;
2594+
return PyFloat_FromDouble(uptime);
2595+
}
2596+
#endif
2597+
2598+
25712599
static PyMethodDef TestMethods[] = {
25722600
{"set_errno", set_errno, METH_VARARGS},
25732601
{"test_config", test_config, METH_NOARGS},
@@ -2663,6 +2691,9 @@ static PyMethodDef TestMethods[] = {
26632691
{"test_atexit", test_atexit, METH_NOARGS},
26642692
{"code_offset_to_line", _PyCFunction_CAST(code_offset_to_line), METH_FASTCALL},
26652693
{"toggle_reftrace_printer", toggle_reftrace_printer, METH_O},
2694+
#ifdef HAVE_SYSCTLBYNAME
2695+
{"uptime_bsd", uptime_bsd, METH_NOARGS},
2696+
#endif
26662697
{NULL, NULL} /* sentinel */
26672698
};
26682699

configure

Lines changed: 12 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

configure.ac

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3079,7 +3079,8 @@ AC_CHECK_HEADERS([ \
30793079
sys/endian.h sys/epoll.h sys/event.h sys/eventfd.h sys/file.h sys/ioctl.h sys/kern_control.h \
30803080
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 \
30813081
sys/random.h sys/resource.h sys/select.h sys/sendfile.h sys/socket.h sys/soundcard.h sys/stat.h \
3082-
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 \
3082+
sys/statvfs.h sys/sys_domain.h sys/syscall.h sys/sysctl.h \
3083+
sys/sysmacros.h sys/termio.h sys/time.h sys/times.h sys/timerfd.h \
30833084
sys/types.h sys/uio.h sys/un.h sys/utsname.h sys/wait.h sys/xattr.h sysexits.h syslog.h \
30843085
termios.h util.h utime.h utmp.h \
30853086
])
@@ -5339,7 +5340,7 @@ AC_CHECK_FUNCS([ \
53395340
setresuid setreuid setsid setuid setvbuf shutdown sigaction sigaltstack \
53405341
sigfillset siginterrupt sigpending sigrelse sigtimedwait sigwait \
53415342
sigwaitinfo snprintf splice strftime strlcpy strsignal symlinkat sync \
5342-
sysconf tcgetpgrp tcsetpgrp tempnam timegm times tmpfile \
5343+
sysconf sysctlbyname tcgetpgrp tcsetpgrp tempnam timegm times tmpfile \
53435344
tmpnam tmpnam_r truncate ttyname_r umask uname unlinkat unlockpt utimensat utimes vfork \
53445345
wait wait3 wait4 waitid waitpid wcscoll wcsftime wcsxfrm wmemcmp writev \
53455346
])

pyconfig.h.in

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1354,6 +1354,9 @@
13541354
/* Define to 1 if you have the 'sysconf' function. */
13551355
#undef HAVE_SYSCONF
13561356

1357+
/* Define to 1 if you have the 'sysctlbyname' function. */
1358+
#undef HAVE_SYSCTLBYNAME
1359+
13571360
/* Define to 1 if you have the <sysexits.h> header file. */
13581361
#undef HAVE_SYSEXITS_H
13591362

@@ -1458,6 +1461,9 @@
14581461
/* Define to 1 if you have the <sys/syscall.h> header file. */
14591462
#undef HAVE_SYS_SYSCALL_H
14601463

1464+
/* Define to 1 if you have the <sys/sysctl.h> header file. */
1465+
#undef HAVE_SYS_SYSCTL_H
1466+
14611467
/* Define to 1 if you have the <sys/sysmacros.h> header file. */
14621468
#undef HAVE_SYS_SYSMACROS_H
14631469

0 commit comments

Comments
 (0)