Skip to content

Commit 1926cf3

Browse files
[3.15] gh-151929: Get uptime on BSD/macOS in pythoninfo (GH-152189) (#152196)
gh-151929: Get uptime on BSD/macOS in pythoninfo (GH-152189) * Check sysctlbyname() function and sys/sysctl.h header in configure. * Add _testcapi.uptime_bsd() function. (cherry picked from commit b6d89ed) Co-authored-by: Victor Stinner <vstinner@python.org>
1 parent a53c6ca commit 1926cf3

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
@@ -1083,6 +1083,18 @@ def uptime_linux():
10831083
return
10841084

10851085

1086+
def uptime_bsd():
1087+
# Get sysctlbyname("kern.boottime")
1088+
try:
1089+
import _testcapi
1090+
except ImportError:
1091+
return None
1092+
try:
1093+
return _testcapi.uptime_bsd()
1094+
except (AttributeError, OSError):
1095+
return None
1096+
1097+
10861098
def uptime_windows():
10871099
try:
10881100
import _winapi
@@ -1093,7 +1105,7 @@ def uptime_windows():
10931105

10941106

10951107
def get_uptime():
1096-
for func in (uptime_boottime, uptime_linux, uptime_windows):
1108+
for func in (uptime_boottime, uptime_linux, uptime_bsd, uptime_windows):
10971109
uptime = func()
10981110
if uptime is not None:
10991111
return uptime
@@ -1107,9 +1119,15 @@ def get_machine_id():
11071119
if machine_guid:
11081120
return machine_guid
11091121

1110-
machine_id = read_first_line("/etc/machine-id")
1111-
if machine_id:
1112-
return machine_id
1122+
for filename in (
1123+
# https://www.freedesktop.org/software/systemd/man/latest/machine-id.html
1124+
"/etc/machine-id",
1125+
# BSD
1126+
"/etc/hostid",
1127+
):
1128+
machine_id = read_first_line(filename)
1129+
if machine_id:
1130+
return machine_id
11131131

11141132
return None
11151133

@@ -1119,7 +1137,6 @@ def collect_linux(info_add):
11191137
if boot_id:
11201138
info_add('system.boot_id', boot_id)
11211139

1122-
# https://www.freedesktop.org/software/systemd/man/latest/machine-id.html
11231140
machine_id = get_machine_id()
11241141
if machine_id:
11251142
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"
@@ -2970,6 +2973,31 @@ test_soft_deprecated_macros(PyObject *Py_UNUSED(self), PyObject *Py_UNUSED(args)
29702973
Py_RETURN_NONE;
29712974
}
29722975

2976+
2977+
#ifdef HAVE_SYSCTLBYNAME
2978+
static PyObject*
2979+
uptime_bsd(PyObject *Py_UNUSED(self), PyObject *Py_UNUSED(args))
2980+
{
2981+
struct timeval tv;
2982+
size_t size = sizeof(tv);
2983+
int res = sysctlbyname("kern.boottime", &tv, &size, NULL, 0);
2984+
if (res != 0) {
2985+
return PyErr_SetFromErrno(PyExc_OSError);
2986+
}
2987+
double boottime = (double)tv.tv_sec + tv.tv_usec * 1e-6;
2988+
2989+
PyTime_t now_t;
2990+
if (PyTime_Time(&now_t) < 0) {
2991+
return NULL;
2992+
}
2993+
double now = PyTime_AsSecondsDouble(now_t);
2994+
2995+
double uptime = now - boottime;
2996+
return PyFloat_FromDouble(uptime);
2997+
}
2998+
#endif
2999+
3000+
29733001
static PyMethodDef TestMethods[] = {
29743002
{"set_errno", set_errno, METH_VARARGS},
29753003
{"test_config", test_config, METH_NOARGS},
@@ -3076,6 +3104,9 @@ static PyMethodDef TestMethods[] = {
30763104
{"test_thread_state_ensure_detachment", test_thread_state_ensure_detachment, METH_NOARGS},
30773105
{"test_thread_state_ensure_detached_gilstate", test_thread_state_ensure_detached_gilstate, METH_NOARGS},
30783106
{"test_thread_state_release_with_destructor", test_thread_state_release_with_destructor, METH_NOARGS},
3107+
#ifdef HAVE_SYSCTLBYNAME
3108+
{"uptime_bsd", uptime_bsd, METH_NOARGS},
3109+
#endif
30793110
{NULL, NULL} /* sentinel */
30803111
};
30813112

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
@@ -3159,7 +3159,8 @@ AC_CHECK_HEADERS([ \
31593159
sys/endian.h sys/epoll.h sys/event.h sys/eventfd.h sys/file.h sys/ioctl.h sys/kern_control.h \
31603160
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 \
31613161
sys/random.h sys/resource.h sys/select.h sys/sendfile.h sys/socket.h sys/soundcard.h sys/stat.h \
3162-
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 \
3162+
sys/statvfs.h sys/sys_domain.h sys/syscall.h sys/sysctl.h \
3163+
sys/sysmacros.h sys/termio.h sys/time.h sys/times.h sys/timerfd.h \
31633164
sys/types.h sys/uio.h sys/un.h sys/utsname.h sys/wait.h sys/xattr.h sysexits.h syslog.h \
31643165
termios.h util.h utime.h utmp.h \
31653166
])
@@ -5496,7 +5497,7 @@ AC_CHECK_FUNCS([ \
54965497
setresuid setreuid setsid setuid setvbuf shutdown sigaction sigaltstack \
54975498
sigfillset siginterrupt sigpending sigrelse sigtimedwait sigwait \
54985499
sigwaitinfo snprintf splice strftime strlcpy strsignal symlinkat sync \
5499-
sysconf tcgetpgrp tcsetpgrp tempnam timegm times tmpfile \
5500+
sysconf sysctlbyname tcgetpgrp tcsetpgrp tempnam timegm times tmpfile \
55005501
tmpnam tmpnam_r truncate ttyname_r umask uname unlinkat unlockpt utimensat utimes vfork \
55015502
wait wait3 wait4 waitid waitpid wcscoll wcsftime wcsxfrm wmemcmp writev \
55025503
])

pyconfig.h.in

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

1390+
/* Define to 1 if you have the 'sysctlbyname' function. */
1391+
#undef HAVE_SYSCTLBYNAME
1392+
13901393
/* Define to 1 if you have the <sysexits.h> header file. */
13911394
#undef HAVE_SYSEXITS_H
13921395

@@ -1491,6 +1494,9 @@
14911494
/* Define to 1 if you have the <sys/syscall.h> header file. */
14921495
#undef HAVE_SYS_SYSCALL_H
14931496

1497+
/* Define to 1 if you have the <sys/sysctl.h> header file. */
1498+
#undef HAVE_SYS_SYSCTL_H
1499+
14941500
/* Define to 1 if you have the <sys/sysmacros.h> header file. */
14951501
#undef HAVE_SYS_SYSMACROS_H
14961502

0 commit comments

Comments
 (0)