Long running PHP script gotcha

So I was recently answering a question on StackOverflow, and learned something quite interesting about PHP.  This particular aspect of PHP mostly affects long running scripts, such as PHP based servers or daemons.

PHP does not re-use resource ids internally, so eventually your script could run into an error with the resource ID overflows and wraps around into the negatives, which pretty much breaks everything. There was a bug report opened about it in 2009, but the issue is still present. This is a huge issue, because resources are used all over, even in not-so-apparent places. For example, most file operations use resources, as do database connections and network sockets. Some of these are obvious, as functions return a resource object (such as socket_accept). Others are not obvious, like file_get_contents, which actually uses two resources under the hood, incrementing the internal resource ID counter by two

The maximum resource id depends on your architecture (32 or 64 bit), and possibly the options used to compile PHP. On 32 bit systems, it’s almost certainly going to be 2,147,483,647. On 64 bit systems, its probably going to be 9,223,372,036,854,775,807.

While this limit is far easier to hit on 32 bit systems, it’s still possible on 64 bit systems if your script is very long running. This limit is good to be aware of when designing your application, as it’s possible to mitigate by using techniques such as forking and multiple processes.

Demonstration:

<?php
echo gmp_init("0x41682179fbf5")."\n";// Resource id #4
echo gmp_init("0x41682179fbf5")."\n";// Resource id #5
echo gmp_init("0x41682179fbf5")."\n";// Resource id #6
file_get_contents('/etc/hosts');
echo gmp_init("0x41682179fbf5")."\n";// Resource id #9
echo gmp_init("0x41682179fbf5")."\n";// Resource id #10
echo gmp_init("0x41682179fbf5")."\n";// Resource id #11

The above code will demonstrate resource IDs incrementing if you run it locally (requires php5-gmp). You can also see file_get_contents incrementing the ID by two.

Leave a Reply