Jon Marnock <[email protected]> writes:
> I know this is an ancient thread, but I just got weewx up and running on
> OpenBSD and found the FreeBSD kern.boottime thing didn't work for system
> uptime because the sysctlbyname doesn't exist there.
The try block that has a comment about FreeBSD works on NetBSD also,
which has sysctlbyname. I would expect it to also work on Dragonfly.
(On NetBSD, it seems /proc/uptime is there with a Linux-compatible value,
so the first method works, if /proc is mounted.)
> I've never programmed in python before, so I'm sure this is horrible, but
> following the example of the FreeBSD sysctlbyname modification, I've
> created one that works in OpenBSD:
Most of the complexity seems unavoidable. I might consider hoisting the
cyptes/libc up a level, but I think it's better to have each try block
be logically self-contained.
> bin/weewx/station.py
> @@ -118,7 +118,22 @@
> libc.sysctlbyname("kern.boottime", ctypes.byref(buf),
> ctypes.byref(size), None, 0)
> os_uptime_secs = time.time() - float(buf.value)
> except (AttributeError, IOError, NameError):
> - pass
> + try:
> + # for OpenBSD
> + import ctypes
> + from ctypes.util import find_library
> + libc = ctypes.CDLL(find_library('c'))
> + # Confession: I don't know how to get a ctype
> struct for timeval. It's just two longs stacked next to each other and we
> only care about the first, so this currently works:
> + boottime = (ctypes.c_long*2)(0, 0)
> + size = ctypes.c_size_t()
> + size.value = ctypes.sizeof(boottime)
> + CTL_KERN = 1
> + KERN_BOOTTIME = 21
> + mibs = (ctypes.c_int*2)(CTL_KERN, KERN_BOOTTIME)
> + libc.sysctl(ctypes.byref(mibs), len(mibs),
> ctypes.byref(boottime), ctypes.byref(size), None, 0)
> + os_uptime_secs = time.time() - float(boottime[0])
> + except:
> + pass
>
> return weewx.units.ValueHelper(value_t=(os_uptime_secs, "second",
> "group_deltatime"),
> formatter=self.formatter,
Is it really still two longs? On NetBSD it seems to be struct timespec,
which is a time_t and a long, and time_t is int64_t.
> As this uses a more generic sysctl call it's possible this will also work
> in FreeBSD and possibly more generally for other unixes that don't have
> procfs available handy, so it's entirely possible this could replace the
> current FreeBSD block.
There are two problems with this being a generic approach. One is the
numeric codepoints. On NetBSD 21 is OBOOTTIME, which returns struct
timeval50 which is two longs -- but only if COMPAT50 is defined in the
kernel config. KERN_BOOTTIME is 83, which returns struct timespec.
The other problem already exists, which is that the return types are not
necessarily the same on various systems.
> I don't have FreeBSD handy to test though, so... YMMV :)
Odds are that it might work as a compat call, but that shouldn't be
used.
Overall, I would want to replace the try/except/try notion with a switch
on os type and helper functions for groups of systems that have common
behavior. That's perhaps a bias on my part not to use exceptions for
things that could avoid them, and partly because this seems to be
getting to be a long list.
Also, I wonder about using a library. I realize adding a dependency vs
a bit of icky code is a hard call. And, I didn't quickly find a
maintained library for this. So I'd change the code to try
/proc/uptime, or at least on Linux and NetBSD, and then have a switch on
OS type with whatever that OS needs.