Hacker News new | past | comments | ask | show | jobs | submit login

I think the best way of doing this is a 4 step approach:

1. Old situation, time_t is 32-bit

2. Migration starts, time_t is 32-bit by default, -D_TIME_BITS=64 to get 64-bits

3. Migration continues, time_t is 64-bit by default, -D_TIME_BITS=32 to get 32-bits

4. New situation, time_t is 64-bit

And with a long time between these steps. So glibc is at step 2 while musl skipped step 2 and is at step 3. There should be plenty of time between steps. It might make sense to keep it at step 3 until 2037 or so for very restrictive embedded plaforms etc.




It may be an idea to have a step between 2 and 3 with NO default, to force everyone who compiles their code against your header files to make their choice explicit.


That would be untenable - I wouldn't be able to cleanly `gcc -o blah blah.c` without making an explicit decision, and by extension wouldn't be able to (continue to) compile existing code either.

Rebuilds on every codebase everywhere ever would promptly blow up.

IMHO the revolts would come from two camps, a) bureaucracies for whom a build system change would normally take months, and b) individual devs who would be all like "compilation flags?? in MY defaults?! that's LESS likely than you think!".

Worst case scenario, someone forks glibc, removes the offending requirement, proffers commercial support for their fork... and ends up making bank.


Blowing up rebuilds is basically the point, and there is a simple fix in the make file or whatever to keep the status quo.

For the bureaucracies of case (a), a change of glibc or, more so, gcc should then take many years if they take the impact of changes seriously.


> Rebuilds on every codebase everywhere ever would promptly blow up.

Only if they use time_t, but I get the point.


In other words, all non-trivial code builds would break? Sounds unreasonably painful.


painful yes, but isn't that a win? If it's breaking at build time, that means someone's actually /building/ their app. And the fix is easy enough (as long a they don't set it to 32 bit...).

The bigger issue is all the systems that won't be rebuilt (per several sibling comments).

--

EDIT: fixed grammar.


There is no "no default", your distro will ship with one or the other. Very few people compile and ship glibc, upstream defaults only matter in the way they affect distro defaults.


The macros aren't set when building the libc, they are set when programs using the libc are build. So every program build on a distribution uses either the default or set one of the macros.


That's interesting, how does glibc maintain ABI compatibility? Alias attributes?

Even if glibc does it, if other libraries expose time_t in their ABI and don't do the same, then it's the same problem.


> [H]ow does glibc maintain ABI compatibility? Alias attributes?

Symbol versioning[1,2]. Kind of like aliases, but more awkward. In theory it’s not specific to glibc, in practice hardly anyone else bothers being so careful about their ABI.

Note that dynamically linked musl, which Alpine uses (I think..?), doesn’t understand symbol versioning, though I expect this will only last until the first ABI break in musl.

[1]: https://www.akkadia.org/drepper/symbol-versioning

[2]: https://maskray.me/blog/2020-11-26-all-about-symbol-versioni...


> Symbol versioning

I know that glibc uses symbol versioning to remain ABI-compatible within versions. What I meant was ABI compatibility between 32-bit and 64-bit time_t with the same glibc library. Looks like it uses something like aliases for that (but self-implemented using asm):

https://sourceware.org/git/?p=glibc.git;a=blob;f=misc/sys/se...

https://sourceware.org/git/?p=glibc.git;a=blob;f=misc/sys/cd...


musl has lasted almost one-third as long as glibc, with significantly less than one-third the number of ABI breaks. as far as I know, the only musl ABI break has been time64; despite glibc's supposedly superior version handling, musl has completed time64 support with headers only, whereas glibc is still in progress.


They are set when building the libc. If you change the macro to something else and then link, you will get code that crashes due to mismatches in ABI.


I think that would be a bad idea in this specific case.

Why? Because for the majority of codebases, the time_t change won't require any work.

You'd be forcing a compiler error, and it would effectively say "Add -D_TIME_BITS=64. If you're doing something really weird with time_t then you may have to update your code too, but in 95% of the cases, you can just add that flag."

I think the compiler error might be warranted for something like "You are using a function that is 95% of the time insecure or wrong, please add -DGAPING_SECURITY_HOLE if you know what you're doing", but if the error really is just "add a flag, you do not need to think about your code probably", the library authors themselves might as well default it for you.


If I understand it correctly glibc is on a mix of 2 and 3, 3 on 64-bit systems and 2 on 32-bit systems.

Though I am not certain 64-bit supports 32-bit time so it may be on 4 there already

I am basing this of these two sites and a quick look at the source code though there may be better documentation on it

https://sourceware.org/glibc/wiki/Y2038ProofnessDesign

https://www.gnu.org/software/libc/manual/html_node/64_002dbi...


64-bit glibc has always had 64-bit time, all this matters only to 32-bit applications.


On transition from step 2 to step 3 there will be a great mess: some libraries in the OS distro are built with sizeof(time_t)=4 assumption and other libraries + application are built with sizeof(time_t)=8 assumption. ABI will break at random boundaries, and not just functions: structures will have incompatible layout etc.

If step 2 is omitted, then similar great mess will happen on transition from step 1 to step 3.

We need a better plan, like modifying compilers (for i686 and other 32-bit targets) to emit '32-bit time_t code' and '64-bit time_t code' simultaneously, and then resolve to proper functions later, at the link time.


Is phase 2 that useful?

Why would you -D_TIME_BITS to something other than the default? It's a hard thing to do safely, since you're choosing to be ABI incompatible (in a way that's not caught at compile or even invocation time) with the system's default.

And then, all you get is a binary that will potentially handle times past 2038 safely, when the whole rest of the system won't.


I think it lets developers opt-in to fixing their glibc-dependent programs ahead of time, so there's less work to do on stage 3.


The thing is, not too much can be expected to break from a 64 bit time_t. Only stuff that directly shoves time_t's over the network or to disk -- a bad practice -- will.

Note anything that builds on x86-64 or other 64 bit architectures has already figured out how to tolerate 64 bit time_t's.

The major reason it's not safe to build with a 64 bit time_t is because you don't know whether other libraries are. If the C library cuts over, when people/distributions move to the new library version, they know that's not a concern.

Defaults change in tooling all the time, requiring code changes for distributions bundling newer tooling/libraries. This one would require less change than most.

Of course, it's possible to survive a 64 bit time_t and still not be 2038-safe. But at least you can be correct if you have a C library and other libraries that will tolerate 64 bit time_t's.


So the fix is to list all libraries in popular distros that break with time_t being 64 bits, file issues for all of them, and track progress somehow. Messing with the defaults is only useful if the ensuing breakage is promptly fixed.


> So the fix is to list all libraries in popular distros that break with time_t being 64 bits

All libraries in popular distros build on x86-64, which in turn means they use a 64 bit time_t there.

It's time for 32 bit architectures to join 64 bit architectures in having a 64 bit time_t.

Anything that ships today in distributions will ship in embedded systems for 5+ years. And then a lot of those embedded systems (too many) will last a long time. 2026 is getting pretty uncomfortably close to 2038.


> Is phase 2 that useful?

Yes for preparing the upgrade seamlessley for developers, administrators and users.

you can prepare your buildscripts before it breaks, you can build it easier as feature/forward/backward toggle

same logic and code with different toggles is better


In practice, all the code in distributions has built in environments with 64 bit time_t. Some end-user legacy code may not be, but it probably isn't much: most things just don't care about a field getting wider behind the scenes.

The big pain, IMO, at this point is the big cutover where all libraries need to move to the new ABI.

This still doesn't prove things as 2038-safe, but it at least means things reasonably can be 2038-safe on 32 bit if they choose... while today it's impossible for practical purposes.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: