This morning I was deploying a quick little fix for an HTML rendering problem. I was performing various substr operations, and I saw I had an off-by-one (say it with me, "O-B-1") error. I fixed the code and pushed it to the server. Within about 3 seconds I realized I had made a pretty awful mistake. The code I pushed had an obvious bug and would never complete; it contained an infinite loop.
No problem, I figured the page would churn for a few seconds and then return PHP exceeded time limit error. Except that didn't happen.
My web browser was hung, and so was my ssh session. I could try to enter commands, but nothing was taking.
I suddenly had a very big problem.
I ended up waking the system administrator and having him reboot the server. I fixed my coding goof and all was well with the world.
The question, though, was how on Earth did I manage to bring down a server with a simple PHP script? That's not supposed to happen.
My first guess was that someone had set a really large timeout in php.ini and as a result, the usual infinite loop protection was gone. A quick check of the php.ini showed that this was not the case. It turned out to be a much more sinister setting. It was this one line:
memory_limit = -1
The -1 in this context tells PHP to go ahead and use as much memory as it wants. This is of course is a terrible, horrible, awful idea. And I just provided why.
With the memory_limit set to -1, my script started consuming massive amounts of memory, and there was no ceiling to stop it. Within a few seconds I had probably allocated all free RAM, and then swap. I couldn't enter commands at my ssh prompt because I wasn't able to swap the process back into memory.
I ended up setting this value to 256Meg, which should be ample for regular use, and not detrimental in the case of an infinite loop.
I learned some time ago that blindly allocating resources is almost always a bad idea. Eventually something is going to give. And you'd rather have it be something controlled, like a PHP process, then the whole dang server.