Hi internals,
- In 2038,
(new DateTime())->getTimestamp()
and other time apis such as strtotime will start throwing "ValueError: Epoch doesn't fit in a PHP integer"
on 32-bit php builds, where PHP'sint
type is 32-bits.
(other APIs will return negative 32-bit integers)
See https://en.wikipedia.org/wiki/Year_2038_problem - Because PHP provides security support for 3 years, and many
*nix
OS LTS releases extend it even longer, we should decide on what to do about
32-bit support well before 2038 (drop it or implement alternatives, and alternatives seem unlikely to support a small fraction of hardware). - Needing to support 32-bit PHP builds limits the APIs that can be included in PHP, and slightly slows down development of PHP, PECLs, and composer packages.
- I think PHP's documentation and tools should start discouraging deploying new 32-bit builds, and give advance notice that it would be removed (if it seems likely 32-bit support will be dropped.)
Repeating the above points in more detail,
- In the year 2038, many of 32-bit php builds' APIs dealing with unix timestamps will stop working.
E.g. in 2038 on a 32-bit build of php,(new DateTime())->getTimestamp()
would throw "ValueError: Epoch doesn't fit in a PHP integer" instead of returning an int,
when the time passes 0x7FFFFFFF. See https://bugs.php.net/bug.php?id=52062 for details.
I'd consider throwing in getTimestamp to be the most reasonable solution, given the return type of those methods isint
, existing code may pass the return value
to a function/property with real type int, etc.
- Although php's security support for a minor release lasts for only 3 years,
some*nix
OSes will make a best effort at unofficially backporting patches to php for the lifetime of that OS's LTS release,
so we could potentially see 32-bit builds for ~10 years (not sure what 32-bit distros there will be in 2028. This number is a guess.)
- on desktop oses, the main use of 32-bit packages on 64-bit hardware seems to be for supporting code released for only one architecture,
e.g. https://ubuntu.com/blog/statement-on-32-bit-i386-packages-for-ubuntu-19-10-and-20-04-lts - Many WordPress servers still run php 5.x.
- If applications running on an OS with 10 years of php support computed dates that are a year in the future,
it'd be useful to prepare 11 years in advance.
There are 17 years until 2038.
Hardware that only has 32-bit support is still running on a small fraction of machines being sold (e.g. cheap laptops),
and 32-bit hardware may last decades after they were manufactured,
but is hopefully a tiny fraction of server/consumer hardware still being manufactured in 2021.
I don't know of 32-bit php running in embedded systems or IoT devices, but haven't looked.
- Aside: It is possible to install a 32-bit only OS on hardware supporting 64-bit architectures, https://www.backblaze.com/blog/64-bit-os-vs-32-bit-os/
If PHP's maintainers decide to drop support for 32-bit builds in a future major/minor release, it would be useful to give users advance notice,
so that they can factor this into decisions on hardware and OSes to use for deploying php in servers or developing locally.
- Needing to support 32-bit PHP builds limits what can be done in the language, and slightly slows down development of PHP, PECLs, and composer packages.
Additionally, continuing to provide 32-bit support constrains what APIs can be provided by the language.
In most cases this isn't an issue, but this came up with PRNG->next64BitInt()
being impractical practical in a recent proposal: https://externals.io/message/112525#112722
- 32-bit installations do reduce the memory usage and installation size of php slightly,
but those installations would have problems with the 2038 problem and supporting use cases that require more than 2-4GB of free memory. - PECLs and composer packages are generally not tested as thoroughly on 32-bit builds.
Maintainers may be less responsive if they're personally unaffected, or don't already have 32-bit builds installed, or don't know from the bug report that 32-bit php was used. - The PHP interpreter (Zend/zend_vm_def.h, etc.) and JIT have different implementations for 32-bit builds, complicating development of php itself.
Hypothetically that could lead to bugs getting released and contributing to the VM being harder to do, but in practice it doesn't seem to be a large issue.
In comparison, other languages I've used would have an easier time continuing to support 32-bit builds past 2038.
- Python and Ruby have arbitrary-precision numbers.
- In Java,
int
is 32-bit, andlong
is 64-bit. - Golang and C and rust have
int64_t
andint32_t
equivalents, but also support a separateint
for the native word size. - Javascript only has a
Number
type that is equivalent to 64-bit floats. JS also has a distinct BigInt object type for arbitrary precision numbers.
I'd considered some alternatives, but they didn't seem viable:
a. Changing the signature of getTimestamp(etc.) to int|float
would cause different issues once the floats were used and make static analysis harder - applications may see obvious TypeErrors,
or functions returning early for non-integers, or subtler issues with serializing data as an unexpected type
b. Using 64-bit integers for PHP's int type (zend_long
) (but continuing to use 32-bit pointers, etc.) for PHP's int
didn't seem worth the effort and bugs it may cause.
A lot of php internals or PECL code would implicitly assume that sizeof(zend_long) <= sizeof(size_t), sizeof(void*)
(etc.) and I'd expect changing that to lead to too many bugs to be worth it.
- I have some modest proposals for discouraging the deployment of 32-bit PHP builds before they are removed (if 32 bit builds do get removed):
If the PHP project's leaders or core developers don't have objections to dropping 32-bit support:
a. Decide whether to postpone making a decision, or decide on an approximate year or release to announce that the php project would drop 32-bit support and document that.
to give users and package maintainers advance time to prepare. (e.g. for developers to choose their next computer purchase, avoid hypothetically selling embedded 32-bit hardware with 32-bit php installed, or setting up new servers or shared hosting on 32-bit hardware)
b. Optionally, visually emphasize 64-bit downloads of PHP on the windows download page to make the recommended version obvious to users unfamiliar with the difference between x64 and x86 builds,
similar to how https://golang.org/dl/ highlights 64-bit builds in bold.
(e.g. on https://windows.php.net/download/ , use fainter text color, mention that most use cases use x64, and optionally mention how to check if the OS is 32-bit Windows)
c. In parts of php that would not affect typical PHP applications or servers, mention (when run under 32-bit builds) that 32-bit builds of php may break in 2038 and that users should migrate before then
(e.g., php -a
, php --version
, php --help
, ./configure
, pecl
, near the top of phpinfo()
)
The last time I saw the year 2038 problem mentioned on php-internals was tangentially, in 2014: https://marc.info/?l=php-internals&m=140558153213332&w=2
Thanks,
- Tyson
On Fri, Jan 8, 2021 at 3:47 AM tyson andre tysonandre775@hotmail.com
wrote:
Hi internals,
- In 2038,
(new DateTime())->getTimestamp()
and other time apis such as
strtotime will start throwing "ValueError: Epoch doesn't fit in a PHP
integer"
on 32-bit php builds, where PHP'sint
type is 32-bits.
(other APIs will return negative 32-bit integers)
See https://en.wikipedia.org/wiki/Year_2038_problem- Because PHP provides security support for 3 years, and many
*nix
OS
LTS releases extend it even longer, we should decide on what to do about
32-bit support well before 2038 (drop it or implement alternatives, and
alternatives seem unlikely to support a small fraction of hardware).- Needing to support 32-bit PHP builds limits the APIs that can be
included in PHP, and slightly slows down development of PHP, PECLs, and
composer packages.- I think PHP's documentation and tools should start discouraging
deploying new 32-bit builds, and give advance notice that it would be
removed (if it seems likely 32-bit support will be dropped.)Repeating the above points in more detail,
- In the year 2038, many of 32-bit php builds' APIs dealing with unix
timestamps will stop working.
E.g. in 2038 on a 32-bit build of php,(new DateTime())->getTimestamp()
would throw "ValueError: Epoch doesn't fit in a PHP integer" instead of
returning an int,
when the time passes 0x7FFFFFFF. See https://bugs.php.net/bug.php?id=52062
for details.
I'd consider throwing in getTimestamp to be the most reasonable solution,
given the return type of those methods isint
, existing code may pass the
return value
to a function/property with real type int, etc.
https://www.drupal.org/docs/system-requirements/limitations-of-32-bit-php
- Although php's security support for a minor release lasts for only 3
years,
some*nix
OSes will make a best effort at unofficially backporting
patches to php for the lifetime of that OS's LTS release,
so we could potentially see 32-bit builds for ~10 years (not sure what
32-bit distros there will be in 2028. This number is a guess.)
- on desktop oses, the main use of 32-bit packages on 64-bit hardware
seems to be for supporting code released for only one architecture,
e.g.
https://ubuntu.com/blog/statement-on-32-bit-i386-packages-for-ubuntu-19-10-and-20-04-lts- Many WordPress servers still run php 5.x.
- If applications running on an OS with 10 years of php support computed
dates that are a year in the future,
it'd be useful to prepare 11 years in advance.
There are 17 years until 2038.Hardware that only has 32-bit support is still running on a small fraction
of machines being sold (e.g. cheap laptops),
and 32-bit hardware may last decades after they were manufactured,
but is hopefully a tiny fraction of server/consumer hardware still being
manufactured in 2021.
I don't know of 32-bit php running in embedded systems or IoT devices, but
haven't looked.
- Aside: It is possible to install a 32-bit only OS on hardware supporting
64-bit architectures,
https://www.backblaze.com/blog/64-bit-os-vs-32-bit-os/If PHP's maintainers decide to drop support for 32-bit builds in a future
major/minor release, it would be useful to give users advance notice,
so that they can factor this into decisions on hardware and OSes to use
for deploying php in servers or developing locally.
- Needing to support 32-bit PHP builds limits what can be done in the
language, and slightly slows down development of PHP, PECLs, and composer
packages.Additionally, continuing to provide 32-bit support constrains what APIs
can be provided by the language.
In most cases this isn't an issue, but this came up with
PRNG->next64BitInt()
being impractical practical in a recent proposal:
https://externals.io/message/112525#112722
- 32-bit installations do reduce the memory usage and installation size of
php slightly,
but those installations would have problems with the 2038 problem and
supporting use cases that require more than 2-4GB of free memory.- PECLs and composer packages are generally not tested as thoroughly on
32-bit builds.
Maintainers may be less responsive if they're personally unaffected, or
don't already have 32-bit builds installed, or don't know from the bug
report that 32-bit php was used.- The PHP interpreter (Zend/zend_vm_def.h, etc.) and JIT have different
implementations for 32-bit builds, complicating development of php itself.
Hypothetically that could lead to bugs getting released and contributing
to the VM being harder to do, but in practice it doesn't seem to be a large
issue.In comparison, other languages I've used would have an easier time
continuing to support 32-bit builds past 2038.
- Python and Ruby have arbitrary-precision numbers.
- In Java,
int
is 32-bit, andlong
is 64-bit.- Golang and C and rust have
int64_t
andint32_t
equivalents, but also
support a separateint
for the native word size.- Javascript only has a
Number
type that is equivalent to 64-bit floats.
JS also has a distinct BigInt object type for arbitrary precision numbers.I'd considered some alternatives, but they didn't seem viable:
a. Changing the signature of getTimestamp(etc.) toint|float
would cause
different issues once the floats were used and make static analysis harder
- applications may see obvious TypeErrors,
or functions returning early for non-integers, or subtler issues with
serializing data as an unexpected type
We have some database drivers that return int|string result to accommodate
either 32-bit systems, or 64-bit unsigned integers on 64-bit systems. It's
the best we can do right now, but it certainly makes for ugly type
signatures, and I agree that it would not be an adequate solution for
timestamps.
b. Using 64-bit integers for PHP's int type (
zend_long
) (but continuing
to use 32-bit pointers, etc.) for PHP'sint
didn't seem worth the effort
and bugs it may cause.
A lot of php internals or PECL code would implicitly assume that
sizeof(zend_long) <= sizeof(size_t), sizeof(void*)
(etc.) and I'd expect
changing that to lead to too many bugs to be worth it.
When run on 64-bit systems, this is known as the x32 ABI. While PHP does
not officially support running in this configuration, it does mostly work
fine. Of course, doing the same on a 32-bit system is more problematic --
for performance reasons if nothing else. I don't think anyone has tried
doing this yet.
The option c) that you don't mention is to make integers arbitrary
precision, with fast-paths for either 32-bit or 64-bit integers, depending
on platform. Of course, this is also not quite easy :)
Finally, some people would argue that if you're using timestamps you are
doing it wrong anyway. If you stick with DateTimes, then you don't have a
problem (or do you?)
Overall I'm not really sure what to think about this. I personally don't
have any idea how common PHP is used on 32-bit systems (are there any stats
on that? From OS package installs, composer, etc?) and why it is used
there. I know that running PHP on 32-bit is often faster, but I'm not sure
if people explicitly chose to use 32-bit for that reason.
Regards,
Nikita
- I have some modest proposals for discouraging the deployment of 32-bit
PHP builds before they are removed (if 32 bit builds do get removed):
If the PHP project's leaders or core developers don't have objections to
dropping 32-bit support:a. Decide whether to postpone making a decision, or decide on an
approximate year or release to announce that the php project would drop
32-bit support and document that.
to give users and package maintainers advance time to prepare. (e.g.
for developers to choose their next computer purchase, avoid hypothetically
selling embedded 32-bit hardware with 32-bit php installed, or setting up
new servers or shared hosting on 32-bit hardware)
b. Optionally, visually emphasize 64-bit downloads of PHP on the windows
download page to make the recommended version obvious to users unfamiliar
with the difference between x64 and x86 builds,
similar to how https://golang.org/dl/ highlights 64-bit builds in bold.
(e.g. on https://windows.php.net/download/ , use fainter text color,
mention that most use cases use x64, and optionally mention how to check if
the OS is 32-bit Windows)
c. In parts of php that would not affect typical PHP applications or
servers, mention (when run under 32-bit builds) that 32-bit builds of php
may break in 2038 and that users should migrate before then
(e.g.,php -a
,php --version
,php --help
,./configure
,pecl
,
near the top ofphpinfo()
)The last time I saw the year 2038 problem mentioned on php-internals was
tangentially, in 2014:
https://marc.info/?l=php-internals&m=140558153213332&w=2Thanks,
- Tyson