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.

Ian Goldby
  • 5,609
  • 1
  • 45
  • 81
  • 1
    While I agree this is a good question, it might be too broad for SO. Have you searched the LKML or posted a request? – too honest for this site Jan 26 '16 at 14:24
  • @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." – Ian Goldby Jan 26 '16 at 14:37
  • It's 20+ years from now – n. m. could be an AI Jan 26 '16 at 14:44
  • 4
    @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. – Ian Goldby Jan 26 '16 at 14:46
  • The only system I'm aware of that is currently time_t future proof on 32 bit machines is OpenBSD. – Art Jan 26 '16 at 15:01
  • 1
    @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. – too honest for this site Jan 26 '16 at 15:01
  • 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. – n. m. could be an AI Jan 26 '16 at 15:06
  • @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. – Art Jan 26 '16 at 15:25
  • @Art 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. – n. m. could be an AI Jan 26 '16 at 17:46
  • @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. – Art Jan 26 '16 at 18:04
  • @Art `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. – n. m. could be an AI Jan 26 '16 at 18:39
  • @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. – Art Jan 26 '16 at 20:58
  • 1
    Hello from 2021! Linux 5.6 and above are ready to run past year 2038 on 32-bit systems: https://lkml.org/lkml/2020/1/29/355?anz=web – Emile Cormier Apr 09 '21 at 19:35
  • [Is there any way to get 64-bit time_t in 32-bit programs in Linux?](https://stackoverflow.com/q/14361651/995714) – phuclv Jun 08 '21 at 13:23

3 Answers3

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

Art
  • 19,807
  • 1
  • 34
  • 60
  • 1
    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. – Ian Goldby Jan 27 '16 at 08:25
  • 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. – theking2 Aug 09 '20 at 19:55
  • 1
    Hello from 2021! Linux 5.6 and above are ready to run past year 2038 on 32-bit systems: https://lkml.org/lkml/2020/1/29/355?anz=web – Emile Cormier Apr 09 '21 at 19:35
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).

Ctx
  • 18,090
  • 24
  • 36
  • 51
  • 2
    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. – fuz Jan 26 '16 at 14:37
  • 5
    @FUZxxl I agree ;) But we're talking about embedded here, the impact may be manageable – Ctx Jan 26 '16 at 14:39
  • 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. – fuz Jan 26 '16 at 15:04
  • @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. – chqrlie Jan 26 '16 at 15:07
  • 1
    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? – Zhro Jan 26 '16 at 16:31
  • The new epoch is 2106-02-07T06:28:16Z (Unix epoch + 2^32 s). The 2038 date is when the sign bit flips. – Edgar Bonet Feb 27 '22 at 13:58
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.

chqrlie
  • 131,814
  • 10
  • 121
  • 189
  • 3
    If you're bothered to recompile every binary on the entire system, why not upgrade!? – cat Jan 26 '16 at 16:44
  • 2
    @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. – chqrlie Jan 26 '16 at 17:57