Skip to content

dmesg: get the boot time from CLOCK_BOOTTIME on Linux instead of a utmp record - #672

Open
jayhemnani9910 wants to merge 3 commits into
uutils:mainfrom
jayhemnani9910:dmesg-boot-time-without-utmp
Open

jayhemnani9910 wants to merge 3 commits into
uutils:mainfrom
jayhemnani9910:dmesg-boot-time-without-utmp

Conversation

@jayhemnani9910

@jayhemnani9910 jayhemnani9910 commented Oct 22, 2026 •

Copy link
Copy Markdown
Contributor

dmesg panics for every time format that needs the boot time when utmp has no boot record. That is the case on systems without /run/utmp, such as recent Ubuntu and most containers:

$ dmesg -K k.kmsg --time-format=ctime
thread 'main' panicked at src/uu/dmesg/src/time_formatter.rs:149:54:
called `Option::unwrap()` on a `None` value

The same panic hits --time-format=iso and reltime, --since and --until. The tests don't catch it because they build with fixed-boot-time.

On Linux the boot time is now the current time minus CLOCK_BOOTTIME, so no utmp is needed. macOS and FreeBSD read kern.boottime, and other Unix systems keep the utmp lookup. When no boot time can be found, dmesg exits 1 with cannot get the system boot time instead of panicking. uu_dmesg already used uucore::libc without enabling uucore's libc feature, so the crate only built next to another tool that enabled it. The feature is now enabled in its Cargo.toml.

New unit test boot_time_matches_proc_uptime checks the boot time against /proc/uptime. It needs a build without fixed-boot-time, so CI now also runs cargo test -p uu_dmesg; on macOS that runs boot_time_comes_from_kern_boottime. The uptime test fails on the old code on a system without a utmp boot record. cargo clippy -p uu_dmesg --all-targets is clean for armv7-linux-androideabi, x86_64-apple-darwin, x86_64-unknown-freebsd and i686-unknown-freebsd. cargo test for the tools that build here (all but lsipc, lslocks and lsns, which need libsmartcols): 232 passed, same as main. clippy and fmt are clean. With a kmsg file, --time-format=ctime, iso and reltime print the same times as util-linux 2.41.3 (iso differs by 1 µs of rounding).

Copilot AI balanced review requested due to automatic review settings October 22, 2026 05:18

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

An organization owner can choose the repository organization as the billing source for reviews requested by members with a paid Copilot license. Learn about Copilot code review billing. Review the Copilot code review billing settings.

#[cfg(not(any(target_os = "openbsd", target_os = "linux", target_os = "android")))]
fn boot_time() -> DateTime<FixedOffset> {
*BOOT_TIME.get_or_init(|| boot_time_from_utmpx().unwrap())
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this still panics on macOS/freebsd without a boot record, no?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes. In efc8d5d macOS and FreeBSD read kern.boottime with sysctl instead of utmp. When no boot time can be found, on any system, dmesg now exits 1 with dmesg: cannot get the system boot time instead of panicking. With --since or --until it fails before reading any records.

Comment thread src/uu/dmesg/src/time_formatter.rs Outdated
};
// SAFETY: `uptime` is a valid timespec for clock_gettime to write.
unsafe { libc::clock_gettime(libc::CLOCK_BOOTTIME, &mut uptime) };
let uptime = TimeDelta::new(uptime.tv_sec, uptime.tv_nsec as u32).unwrap_or_default();

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

tv_sec is i32 on 32-bit android, does this build there?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It didn't: cargo check --target armv7-linux-androideabi failed with expected i64, found i32 on tv_sec. efc8d5d converts it when the pointer width isn't 64, as uucore's uptime does. cargo clippy -p uu_dmesg --all-targets is now clean for armv7-linux-androideabi, x86_64-apple-darwin, x86_64-unknown-freebsd and i686-unknown-freebsd.

Comment thread src/uu/dmesg/src/time_formatter.rs Outdated
tv_nsec: 0,
};
// SAFETY: `uptime` is a valid timespec for clock_gettime to write.
unsafe { libc::clock_gettime(libc::CLOCK_BOOTTIME, &mut uptime) };

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please check the return value
if it fails, the boot time silently becomes now

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done in efc8d5d: if clock_gettime returns nonzero there is no boot time, so dmesg reports the error instead of using now.

use super::*;

#[test]
fn boot_time_matches_proc_uptime() {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this test never runs in CI, cargo test enables fixed-boot-time
could you please add a cargo test -p uu_dmesg step?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added cargo test -p uu_dmesg to the test job in efc8d5d, after the workspace cargo test, so it runs on all three OSes. On macOS it runs the new boot_time_comes_from_kern_boottime.

Copilot AI balanced review requested due to automatic review settings October 23, 2026 07:08

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

An organization owner can choose the repository organization as the billing source for reviews requested by members with a paid Copilot license. Learn about Copilot code review billing. Review the Copilot code review billing settings.

Comment thread src/uu/dmesg/src/time_formatter.rs Outdated
if res != 0 {
return None;
}
#[cfg(target_pointer_width = "64")]

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same 4 lines as in the linux version, could be a small helper, no?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done in 440d4b8: time_t_secs does the conversion for both. A plain .into() covers 32 and 64-bit time_t, with useless_conversion allowed for the 64-bit case. cargo clippy -p uu_dmesg --all-targets -- -D warnings is clean for x86_64 Linux, macOS and FreeBSD, i686 FreeBSD and armv7 Android.

Copilot AI balanced review requested due to automatic review settings October 24, 2026 18:59

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has insufficient remaining quota.

An organization owner can choose the repository organization as the billing source for reviews requested by members with a paid Copilot license. Learn about Copilot code review billing. Review the Copilot code review billing settings.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants