Saturday, 3 September 2011

Stock components: Nothing can go wrong…go wrong…go wrong…«boom!»

(Yes, Westworld had a view of modern software that's not so far off the mark, considering it was made in 1973.)

I use Macs for development, using both the native Unix OS and one or more VMWare Fusion VMs of Linux, BSD Unix or Windows, depending on the need. Even when I'm going to be deploying on a Linux or Unix server, I prefer to do my basic work using OS X native tools1.

Usually, all that rather famously Just Works. Sometimes, however, it provides lessons in the raving optimism that is Murphy's Law.

The remainder of this post is a summary of Wiki notes I made in chasing down one such occurrence.

This affects only the iMac, not the MacBook Pro2.

The Problem

PHP 5.3.4 as bundled with OS X does not work from Apache 2.2.14, also as bundled with OS X. This appears to have broken with the 10.6.7 update, as noted by many people, and was not fixed by updating to 10.6.8.

Pink Herring

(Not quite a red herring, mind you; just very close to one.)

One of the first things I thought of was to check what modifications had been made to php.ini over the course of time. Every time a new update to the PHP engine was installed as part of Apple's Software Update, the previous contents of the file were saved under a (nominally) intuitive name.

As of Saturday 3 September 2011, the iMac's /etc/ directory contained the following variants of php.ini:

-rw-r--r--  1 peerless  wheel  68920 Sep  3 12:37 php.ini
-rw-r--r--  1 peerless  wheel  45816 Oct 12  2009 php.ini-5.2-previous
-rw-r--r--  1 peerless  wheel  68920 Aug 13 19:11 php.ini.applesaved
-r--r--r--  1 peerless  wheel  69060 Dec 16  2010 php.ini.default
-r--r--r--  1 peerless  wheel  45104 Aug 25  2009 php.ini.default-5.2-previous

At this point, of course, I'm starting to say "uh-oh; a five-way diff?" Silly me; there's an easier way to deal with differences3. We'll get to that at another time; regardless of its usefulness in the current situation, it would be good information to have.


Then I thought, "hang on, have I checked the Apache logs?" Err... not yet. So, I opened a new browser tab and attempted to open http://localhost/~peerless/index1.php, which visibly failed; no output was rendered by the browser.

First off, check /var/log/apache2/access_log. Therein lies the first clue: - - [03/Sep/2011:15:44:41 +0800] "GET /~peerless/index1.php HTTP/1.1" 200 20 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_6_8) AppleWebKit/535.1 (KHTML, like Gecko) Chrome/14.0.835.126 Safari/535.1"

The 200 code means that the file was successfully sent, but it's a lot longer than 20 bytes. Clearly, something fell over and couldn't get up.

Looking at /var/log/apache2/error_log yields the crucial bit.

[Sat Sep 03 15:44:41 2011] [error] [client] PHP Fatal error:  Unknown: apc_fcntl_unlock failed: in Unknown on line 0

A quick bit of google-fu established that the APC PECL extension to PHP has a known bug in it (which is fixed in a release that should ship Any Day Now). I have three options available for action:

  1. Wait for the patch to be rolled up into a new release version, and upgrade my installed copy of APC;
  2. Pull the source for APC, make the change myself, and hand-build the extension; or
  3. Get rid of APC entirely, since this is strictly a dev machine that (for now) doesn't need to worry about caching at all.

A few seconds after implementing option 3, refreshing the index1.php page in the browser caused it to display as expected.

PHP is up again! Great rejoicing was heard through all the land! (Well, at least the room.)

Future Action

Moral of the story: At some point in the not-too-distant future, I Really Should go through the installed PEAR and PECL extensions and get rid of any I'm not actively using. That's what VMs are for: letting me try out various configurations as needed, without stepping on the main system. Oops.4.

Additionally, we still haven't answered the question: why are there five different versions of php.ini?


1. Alternatively, for non-Windows OSs, I can use sshfs with MacFUSE to mount the VMs "hard disk" as part of the OS X file system. With Windows I go the other way; have VMWare share a directory on the host Mac with the Windows instance. (Return)

2. This turned out to be because APC was never installed on the MBP. But we'll get to that. (Return)

3. One easy way(for a competent dev, at least): whip up a VCS repository and add each file in turn, by date, as php.ini. Then use the VCS' diff tool to generate patches from each to the next. (Return)

4. And writing this page took several times as long as actually solving the problem. (Return)