uptime code does not work on FreeBSD with python 3

Bug #1853160 reported by Mina Galić
12
This bug affects 2 people
Affects Status Importance Assigned to Milestone
cloud-init
Fix Released
Medium
Mina Galić

Bug Description

The uptime code in cloudinit/util.py does not work for FreeBSD (any more)

https://github.com/canonical/cloud-init/blob/3baabe76a70b28abeee2da77826a35e27cf9019a/cloudinit/util.py#L1806-L1825 (link to the code in question at the time of reporting)

root@container-host-02:~ # python3.6
Python 3.6.9 (default, Oct 24 2019, 01:18:01)
[GCC 4.2.1 Compatible FreeBSD Clang 6.0.1 (tags/RELEASE_601/final 335540)] on freebsd12
Type "help", "copyright", "credits" or "license" for more information.
>>> import ctypes
>>> libc = ctypes.CDLL('/lib/libc.so.7')
>>> import time
>>> size = ctypes.c_size_t()
>>> buf = ctypes.c_int()
>>> size.value = ctypes.sizeof(buf)
>>> libc.sysctlbyname("kern.boottime", ctypes.byref(buf), ctypes.byref(size), None, 0)
-1
>>>
root@container-host-02:~ #

and here's what happens when we ask for kern.boottime via sysctl(8):

root@container-host-02:~ # sysctl kern.boottime
kern.boottime: { sec = 1573656128, usec = 384300 } Wed Nov 13 14:42:08 2019
root@container-host-02:~ #

Tags: freebsd
Mina Galić (minagalic)
tags: added: freebsd
Revision history for this message
Mina Galić (minagalic) wrote :

my current attempt to bring this into the new millenium:

import ctypes
import time
import errno

class timeval(ctypes.Structure):
    _fields_ = [
        ("tv_sec", ctypes.c_int64),
        ("tv_usec", ctypes.c_int64)
    ]

libc = ctypes.CDLL('/lib/libc.so.7', use_errno=True)
boottime = timeval()
if libc.sysctlbyname("kern.boottime", ctypes.byref(boottime), ctypes.sizeof(timeval), None, 0) == -1:
    print(errno.errorcode[ctypes.get_errno()])
    exit(1)

which results in ENOENT

which is rather confusing, given that `sysctl kern.boottime` returns
kern.boottime: { sec = 1573656128, usec = 384300 } Wed Nov 13 14:42:08 2019

Revision history for this message
Mina Galić (minagalic) wrote :

soooooo!

there are two different issues here at play, which confused me a lot

Let's get the simplest one out of the way: ENOENT is caused by the fact that we're passing a Python String to a C function.

when using b"kern.boottime" + "\x00", it works as expected.

The issue in the original code is that kern.boottime is not an integer (any more… and has not been for a long time…)

There are two ways to unpack it: either by loading the value into a generic string buffer: https://github.com/Cairnarvon/uptime/blob/master/src/__init__.py#L135 and then using struct.unpack

or, as i tried above, by constructing a Structure of our own.

Mina Galić (minagalic)
summary: - uptime code does not work on FreeBSD
+ uptime code does not work on FreeBSD with python 3
Revision history for this message
Mina Galić (minagalic) wrote :
Ryan Harper (raharper)
Changed in cloud-init:
importance: Undecided → Medium
status: New → In Progress
Revision history for this message
Chad Smith (chad.smith) wrote :
Changed in cloud-init:
status: In Progress → Fix Committed
assignee: nobody → Igor Galić (i.galic)
Dan Watkins (oddbloke)
Changed in cloud-init:
status: Fix Committed → Fix Released
Revision history for this message
James Falcon (falcojr) wrote :
To post a comment you must log in.
This report contains Public information  
Everyone can see this information.

Other bug subscribers

Remote bug watches

Bug watches keep track of this bug in other bug trackers.