chrono icon indicating copy to clipboard operation
chrono copied to clipboard

Panic with 0.4.20 on latest ArchLinux and Alpine

Open jcamiel opened this issue 3 years ago • 19 comments

With chrono 0.4.20, using let now: DateTime<Local> = Local::now(); results in a panic.

thread 'main' panicked at 'unable to parse localtime info: Io(Os { code: 2, kind: NotFound, message: "No such file or directory" })', /root/.cargo/registry/src/[github.com](http://github.com/)-1ecc6299db9ec823/chrono-0.4.20/src/offset/local/[unix.rs:95](http://unix.rs:95/):37
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

Repro step:

  1. use latest ArchLinux docker image $ docker run -it archlinux
  2. install rust $ pacman -Sy rust
  3. create a sample
$ cargo init foo
$ cd cargo
$ cargo add chrono
$ cargo run
  1. Edit the main and rerun
use chrono::{DateTime, Local};

fn main() {
    let _now: DateTime<Local> = Local::now();
}

jcamiel avatar Aug 05 '22 08:08 jcamiel

Sorry for the regression! Do Arch/Alpine store the tzdb somewhere else or do they not have it installed at all by default?

djc avatar Aug 05 '22 09:08 djc

It looks like this is happening while we're trying to read /etc/localtime, maybe Alpine/Arch use something different for that?

djc avatar Aug 05 '22 09:08 djc

https://wiki.archlinux.org/title/System_time#Time_zone seems to suggest that Arch at least does put that in the usual place.

https://stackoverflow.com/questions/68996420/how-to-set-timezone-inside-alpine-base-docker-image suggests Alpine also follows the usual process.

djc avatar Aug 05 '22 09:08 djc

Ah sorry, I've forgot to tell that I was in a Docker context. Effectively, with the latest alpine image, if set the timezone "by hand"

$ apk add -U tzdata
$ cp /usr/share/zoneinfo/Europe/Paris /etc/localtime
$ cargo run

Everything is ok now ! Sorry for the trouble!

I will just check what to do with the ArchLinux image and report here for reference.

Edit: exactly the same for ArchLinux, just cp /usr/share/zoneinfo/Europe/Paris /etc/localtime and everything is ok

jcamiel avatar Aug 05 '22 10:08 jcamiel

I'm curious, what did you previously get as the local offset in that container?

djc avatar Aug 05 '22 10:08 djc

I don't know how to test it, I just run the latest archlinux or alpine:

On Alpine:

$ docker run -it alpine
$ date
Fri Aug  5 11:22:04 UTC 2022
$ ls -l /etc/localtime
ls: /etc/localtime: No such file or directory
$ find /usr/share/zoneinfo/
find: /usr/share/zoneinfo/: No such file or directory

Then I add the tzdata package:

$ apk add tzdata
$ date
Fri Aug  5 11:32:41 UTC 2022
$ ls -l /etc/localtime 
ls: /etc/localtime: No such file or directory
$ find /usr/share/zoneinfo/
/usr/share/zoneinfo/
/usr/share/zoneinfo/MST7MDT
/usr/share/zoneinfo/Atlantic
/usr/share/zoneinfo/Atlantic/Stanley
/usr/share/zoneinfo/Atlantic/St_Helena
/usr/share/zoneinfo/Atlantic/South_Georgia
/usr/share/zoneinfo/Atlantic/Madeira
...

On ArchLinux:

$ docker run -it archlinux
$ ls -l /etc/localtime 
ls: cannot access '/etc/localtime': No such file or directory
$ find /usr/share/zoneinfo/
/usr/share/zoneinfo/
/usr/share/zoneinfo/MST7MDT
/usr/share/zoneinfo/Atlantic
/usr/share/zoneinfo/Atlantic/Stanley
/usr/share/zoneinfo/Atlantic/St_Helena
/usr/share/zoneinfo/Atlantic/South_Georgia
/usr/share/zoneinfo/Atlantic/Madeira
...

On both Alpine and ArchLinux image, /etc/localtime doesn't exist. On Alpine, /usr/share/zoneinfo/ doesn't exist and is populated by tzdata package. On Alpine, /usr/share/zoneinfo/ exists.

jcamiel avatar Aug 05 '22 11:08 jcamiel

What's surprising (at least it's surprising to me), is that, if I install python3 on ArchLinux I can get access to time.localtime(). Don't know enough to tell if chrono should be able to work on this Docker image "out of the box"...

jcamiel avatar Aug 05 '22 11:08 jcamiel

I just ran into the same issue. With 0.4.20 chrono basically requires one to set up a correct timezone, which is rarely the case in the container images I'm working with.

What about having the code fall back to UTC?

fzgregor avatar Aug 05 '22 11:08 fzgregor

What about having the code fall back to UTC?

That's what I was wondering about, would be nice to check if that's the expected behavior for libc.

djc avatar Aug 05 '22 11:08 djc

I just tried version 0.4.19:

/foo # cargo run
   Compiling libc v0.2.127
   Compiling num-traits v0.2.15
   Compiling num-integer v0.1.45
   Compiling time v0.1.44
   Compiling chrono v0.4.20
   Compiling foo v0.1.0 (/foo)
    Finished dev [unoptimized + debuginfo] target(s) in 6.88s
     Running `target/debug/foo`
thread 'main' panicked at 'unable to parse localtime info: Io(Os { code: 2, kind: NotFound, message: "No such file or directory" })', /root/.cargo/registry/src/github.com-1ecc6299db9ec823/chrono-0.4.20/src/offset/local/unix.rs:95:37
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
/foo # vim Cargo.toml 
/foo # cargo run
    Updating crates.io index
  Downloaded chrono v0.4.19
  Downloaded 1 crate (155.7 KB) in 0.52s
   Compiling chrono v0.4.19
   Compiling foo v0.1.0 (/foo)
    Finished dev [unoptimized + debuginfo] target(s) in 2.77s
     Running `target/debug/foo`
Now: 2022-08-05 11:48:17.657962057 +00:00

I guess that's what we should aim for from a backwards compatibility perspective.

EDIT: Sorry, for reproducibility, I should note that this is inside a pretty empty alpine container. I installed rust via rustup, and followed @jcamiel's instructions .

/foo # cat src/main.rs 
use chrono::{DateTime, Local};

fn main() {
    let now: DateTime<Local> = Local::now();
    eprintln!("Now: {}", now);
}
/foo # cat Cargo.toml 
[package]
name = "foo"
version = "0.1.0"
edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
chrono = "=0.4.19"
/foo # export
export HOME='/root'
export HOSTNAME='49cea9bbd1b3'
export OLDPWD='/'
export PATH='/root/.cargo/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin'
export PWD='/foo'
export SHLVL='1'
export TERM='xterm'

fzgregor avatar Aug 05 '22 11:08 fzgregor

I have the same issue in iOS and android,but in my demo test It‘s OK

dingwujiang avatar Aug 05 '22 11:08 dingwujiang

If anyone wants to start on a patch, I think you'll want to start here:

https://github.com/chronotope/chrono/blob/main/src/offset/local/unix.rs#L51

If not, @esheppa or I will get around to it soon.

djc avatar Aug 05 '22 12:08 djc

@djc is there interest in delegating this logic to https://docs.rs/iana-time-zone/latest/iana_time_zone/ instead of hand rolling this in chrono? get_timezone in this crate returns result on all platforms so errors like this will be easier to avoid.

lopopolo avatar Aug 06 '22 06:08 lopopolo

I thought you were on a dependency reducing spree? 😛

I don't think bringing in dependencies is the solution here, see @esheppa's linked PR.

djc avatar Aug 06 '22 06:08 djc

I also get this on Android (not iOS emulator!):

Thread 'unnamed' panicked at 'unable to parse localtime info: Io(Os { code: 2, kind: NotFound, message: "No such file or directory" })': /Users/mamcx/.cargo/registry/src/github.com-1ecc6299db9ec823/chrono-0.4.20/src/offset/local/unix.rs:95

mamcx avatar Aug 06 '22 17:08 mamcx

I'm hitting this in Termux builds on my Android as well. I'm not familiar with the change or the justification, but it's worth noting that time zone info does not exist on every system. Think about minimal docker containers and such. Chrono should work in the absence of time zone info. Probably the best thing to do is default to UTC.

dead10ck avatar Aug 06 '22 18:08 dead10ck

Hi there, we're experiencing the same problem. We are building dockers with JIB, which is probably the reason we have no access to /etc/localtime.

tbeemster avatar Aug 09 '22 11:08 tbeemster

We have merged #756 as a partial fix for this.

The following cases should be fixed:

  • Android -> the correct localtime should now be available
  • Docker containers with no /etc/localtime -> these will default to UTC

The following cases are likely still broken:

  • iOS

esheppa avatar Aug 09 '22 13:08 esheppa

The Linux and Android fixes are now available on crates.io as part of the 0.4.21 release.

djc avatar Aug 09 '22 15:08 djc