Year 2038 solution for embedded Linux (32 bit)? [duplicate]
Asked Answered
F

3

26

What is the proper way to handle times in C code for 32-bit embedded Linux (ARMLinux) to ensure that the code continues to work properly after 03:14:07 UTC on 19 January 2038 (when a signed 32-bit time_t overflows)? Given that time_t is signed 32-bit on the system I have to use, what are the alternatives?

A considerable amount of googling has uncovered nothing of practical use. Everyone seems to assume that we will all be using 64-bit OSs by then, but this patently isn't true of embedded systems.

On the system I am required to use, __kernel_time_t is defined as a long. Which presumably means that there is no kernel facility for 64 bit time. The version of uClibc is 0.9.29.

I can't believe I'm the only one with this problem, and I don't want to reinvent the wheel.

Fluoroscope answered 26/1, 2016 at 14:20 Comment(14)
While I agree this is a good question, it might be too broad for SO. Have you searched the LKML or posted a request?Catt
@Olaf: I've read about what the Linux kernel authors are doing, but that all revolves around 64-bit systems. I don't think this question is too broad; frankly I doubt that there are that many different ways of doing it anyway, and the answer could quite possibly be "There simply is no universal solution at present for embedded systems."Fluoroscope
It's 20+ years from nowMisjudge
@n.m. In the embedded world 20 years is not very long at all. One of the systems I work on is over 35 years old.Fluoroscope
The only system I'm aware of that is currently time_t future proof on 32 bit machines is OpenBSD.Mundt
@n.m.: Surprisingly there are fields of application which do not release a new device every year. For household appliances, think about e.g. washing machines (not the cheap ones, of course), etc.Catt
Do you mean a 35 years old physical installation or 35 years old software? The former will have to be replaced/updated before 2038 no matter what. For the latter, word size of the target CPU is irrelevant. Use OS/compiler/standaard library combination that supports 64-bit time_t (or time64_t). If you don't choose the combination, report the issue in writing to whoever is responsible for that, and move on. You cannot solve all of their problems.Misjudge
@n.m. Look up what hardware and software is used for controlling nuclear reactors in Canada. It might surprise you. And it might surprise you that they are planning to keep them running until 2050. 35 years isn't much.Mundt
@Mundt More (nuclear) power to them. I hope these systems don't really need to be in sync with real-world clocks, so that the epoch can be defined arbitrarily for them. Just set their clocks to zero somewhere before 2038.Misjudge
@n.m. I would count setting clocks to zero as a "clever solution", I don't believe in them. Unless it's done regularly. I suspect that most problems with time_t will be of the type "if (timeout_time <= current_time) handle_timeout();", which we've already had a bunch of when time_t was 2^31 - 10^9 and people (Oracle was one) used a billion seconds as a timeout impossibly far in the future. No amount of clever tricks will solve that.Mundt
@Mundt if (timeout_time <= current_time) handle_timeout(); One should use a monotonic clock for all such things, never time() or gettimeofday() or any such thing. Of course the monotonic clock can wrap around too, unless you reboot. And of course resetting the epoch is very ugly and may break systems. I wish I had a silver bullet but there's none.Misjudge
@n.m. One "should", but people very often don't. Besides, the best sources of monotonic clocks return timespec which is by POSIX specified to have a time_t type for tv_sec and are also sometimes (but not always) just based on the normal time, but without adjustments. Your best bet is a monotonic clock that returns uptime (popular choice), but lots of systems only keep track of uptime as an offset from the wall-clock time (which is quite back-asswards) which may lead to issues with time_t again.Mundt
Hello from 2021! Linux 5.6 and above are ready to run past year 2038 on 32-bit systems: lkml.org/lkml/2020/1/29/355?anz=webAddie
Is there any way to get 64-bit time_t in 32-bit programs in Linux?Arawak
M
10

There are no silver bullets, tricks or clever solutions. Either use an operating system that has 64 bit time_t or don't use time_t and any OS facilities that depend on it (which includes filesystems, timers, half the network and such) or plan to update the software in the next 20 years.

There are at least two unix-like systems with 64 bit time_t on 32 bit machines: OpenBSD and NetBSD. OpenBSD had a few talks explaining the reasoning behind it: http://www.openbsd.org/papers/eurobsdcon_2013_time_t/index.html

Mundt answered 26/1, 2016 at 15:19 Comment(3)
I've marked this as the answer simply because our final decision was to live with 32-bit time for now and worry about the problem later. Not a great solution IMO but the component I'm working on isn't the only one affected.Fluoroscope
As ARMLinux seems to be based on NetBSD you are save with the 32bit version. But check this in source. It is not marvelous to think 2038 is far in the future. it is less than 18 years from now.Brachial
Hello from 2021! Linux 5.6 and above are ready to run past year 2038 on 32-bit systems: lkml.org/lkml/2020/1/29/355?anz=webAddie
T
8

Time conversion routines would "simply" have to use 2038-01-19:03:14:07Z as the base for Unix Epoch time if the timestamp is below a certain value.

I.e. if your system goes productive in 2010-01-01, you can assume that no timestamp, which is not overflown, is below 1262300400 (which is unix epoch time for that date).

If a lower timestamp is encountered, consider that it has overflown and use 2038-01-19:03:14:07Z as base time. Comparisons have to be taken into account, too.

Not a clean solution, but doable with moderate effort. Better switch to 64-bit timestamps (which doesn't absolutely need a 64-bit system, btw).

Trachoma answered 26/1, 2016 at 14:28 Comment(6)
This is a horribly approach. On my Linux system there are quite a couple of files with time stamps in 1999 or so. Also, when you extract archives you get from elsewhere (such as from a package update), the mtimes may be all screwed up.Paludal
@FUZxxl I agree ;) But we're talking about embedded here, the impact may be manageableTrachoma
The impact of implausible timestamps from the future can be fatal. For example, it completely throws off make or backup programs that operate based on time stamp.Paludal
@FUZxxl: I definitely do not want to be traveling on that date: planes, trains and automobiles... all may be self driving by then, but probably not immune from the Y2G mother of bugs.Stitching
This is pretty ingenious but possible a little too clever. It would certainly be an interesting surprise for anyone who may need to maintain the system after you. Is this a foreshadowing of a future SO post by your replacement?Blandishment
The new epoch is 2106-02-07T06:28:16Z (Unix epoch + 2^32 s). The 2038 date is when the sign bit flips.Syndic
S
4

I assume your embedded system's ABI defines long as 32 bits.

There is no requirement for the time_t type to be signed. Could you possibly make it unsigned long and buy yourself and your descendants an extra 68 years of tranquility? Changing this would require recompiling the kernel, the C library an d all programs and libraries that use time_t... not for the faint of heart! You might as well define it as long long, but this would change many structure layouts and is even more challenging.

Stitching answered 26/1, 2016 at 15:0 Comment(2)
If you're bothered to recompile every binary on the entire system, why not upgrade!?Dowie
@cat: good point! If the OP has sufficient control over the system software stack, he has several options to prevent the problem, upgrading being a much better solution than patching with kernel types, if he does not, there isn't much that can be done.Stitching

© 2022 - 2024 — McMap. All rights reserved.