Posts filed under 'PHP'

PHP: Memory leak in implicit __toString() call with certain functions

See the gory details in http://bugs.php.net/bug.php?id=43450.

Basically, there are function which expect strings and the implicit _toString() call on an object will leak memory. Testcase:

< ?php
    class Foo {
        function __toString() {
            return 'foo';
        }
    }
    for ($i = 0; $i < 1e5; $i++) {

        $o = new Foo;

        # leaks
        md5($o);
        # does not leak
        #md5($o->__toString());

        # does not leak either way
        # strstr($o, 'f');
        #strstr($o->__toString(), 'f');

        if ($i % 1e3 == 0) {
            printf("%u: %1.2f KB\n",
                $i, memory_get_usage(true) / 1024);
        }
    }

Add comment November 30th, 2007

mysqltail

I’ve hacked together a little PHP script which allows to filter mysql log files for sql statements issued by specific users.

Basic usage:

php mysqltail.php /var/log/mysql.log userToFilter [orOtherUser]

It can also be used to pipe an existing logfile:

cat mysql.log | php mysqltail.php - userToFilter

Download: http://markus.fischer.name/lab/php/mysqltail.php.txt

Add comment September 19th, 2006

Web-developing, subversion and multi-developer environment

One of the often encountered problems when developing application in the web environment is their complex setup. It’s not like a desktop application that you can check out, compile and run the source.

You need a proper server environment where your application can run, the components need to have the required version, etc. Setting up web server is not hard but tuning all required parameters takes time. And usually in a team of developers someone is responsible for the configuration management; and there’s a reason for that.

Because of the resources it takes to set up such an environment, the common sense when developing applications is usually that there’s one server for all developers and that there are one or two fixed checkouts of a project. That’s a bit against the philosophy on how versioning systems are designed to work. Each and every developer should have its own checkout. But with a complex environment it’s not always feasable to have this process. When it takes so much resources to have the central development server fine tuned you can bet it takes even more for local development on the developers computer.

My goal was that we have flexibility:

  • have a place were we check out a complte project and multiple (!) developer can work on one checkout (traditional)
  • have a place for each developer on the development server where he can check out as many custom web projects as he wants
  • make it next to zero work to create new apache configurations for new projects (VirtualHosts, etc.)

I solved this with a small PHP class and some shell scripting, which basically can generate working apache VirtualHosts configuration on the fly. For this we need to know a few things first:

  • the path where the apache configuration templates are stored
  • the path to the common checked out projects
  • the base directory for user specific checked out projects
  • where to generate the PHP5 apache configuration
  • where to generate the PHP4 apache configuration

To recognize a directory whether it is a project to be enabled for apache we’ve the following rules for the directory name:

.php4|.php5[.extern]

Within the directory name is the distinction whether it’s an PHP4 or PHP5 project. That’s necessary because we’re running two instances of apache for each version of PHP so we can run both versions as apache modules.

The other directive, .extern, tells us that we want to public this project from our development server live on the internet. Why? Well, customers are everthing but patient, so it happens quite often we hand out URLs of our current development state to our customers. This also means we have to generate separate VirtualHost configuration for those projects.

The same rule applies to the user specific project directory, except that we don’t support .extern there, see below we.

Every project generated from those rules may have the following URLs:

project.dev.company.tld

For e.g. project.php4, not accessibe for customers

project.live.company.tld

For e.g. project.php5.extern

And for user specific checkouts:

project.username.dev.company.tld

In the end it’s dead simple. It took me about 2 days to gather the requirements, talk with the other developers how we could approach this and implement the soluation. Thanks to apaches Include *.conf directive it’s really easy to dynamically generate VirtualHosts and tell apache to restart.

Since ever developer within our company should be able to create new VirtualHosts config on demand, I provided a basic web interface which generates the apache configuration and restarts apache. Restarting apache from within PHP was a bit problematc, because you need to

  • have the proper permissions to restart apache from user www-data (I’m using Debian)
  • take care that running a PHP script which stops apache also terminates this very PHP script

To solve the permission problem I used sudo and creates a sudoers file like this:

Cmnd_Alias WWWEXEC = /data/www/intern/magic-config/generate.sh
www-data ALL = (root) NOPASSWD: WWWEXEC

To properly execute this script I had to put it into background immidiately so it is decoupled from the PHP script:

exec(“sudo /data/www/intern/magic-config/generate.sh&”);

The generate.sh shell script restarts apache.
At the moment I do not plan to release the code for two reasons:

  1. I would need to get permission from my company, but if someone think he would really benefit from it, I may ask for it
  2. It may be to specific anyway to our environment

Add comment July 12th, 2006

PEARs HTTP_Client and custom User-Agent

The only way to get a custom User-Agent string to HTTP_Client is by deriving HTTP_Client and overloading the method _createRequest.

Although HTTP_Client with its constructor provides a way to pass custom headers, the User-Agent header is also set inside HTTP_Request (create by HTTP_Client) which overrides any earlier value.

Add comment February 24th, 2006

First steps with PDO in PHP 5.1

Environment: Windows, CLI, using pdo_odbc.

Here are some observations from my first steps with the new PDO extension.

Good:

  • Exception-Safe (with PDO::ERRMODE_EXCEPTION)
    I wonder how one could every seriously write good application without exceptions (i.e. proper and predictable error handling)
  • Simple, easy API
    The API is so easy, it has so less methods and therefore is easy to grasp. It may all back in complex situations but that I cannot tell that at the moment.

Not so good:

  • Bound parameters/values not working as expected
    I’m not yet sure if it’s because I use pdo_odb or something else. What I tried, I couldn’t get it to working, no matter which way I tried. So I had to revert to using variables direct in the SQL statement.
  • Crashes
    PDO has the bad habit that it crashes PHP where it can. Since I’m under Windows and I’ve no Windows C IDE I can’t help in debugging this problems myself but can only try to come up with reproduceable scripts. PDO seems to completely go havoc when you use the PDO::FETCH_LAZY attribute on PDO::query(). With havoc I mean that it throws back to you errors which aren’t a direct result of using FETCH_LAZY. I observed that I got two different kind of exceptions (Yes, I do love them) when using FETCH_LAZY. Both were Microsoft Access Driver problems, but they didn’t showed up once I stopped using FETCH_LAZY. One problem was error code 1311 and the other 1310. The former has something to do with running out of memory and the second one with an invalid table id.Then it seems, unreproduceable in small scripts, that it crashes when doing clean up at the end of the script. So basically, you’re doing your thing and when the script ends it gives you the send report to microsoft dialog

Add comment February 5th, 2006

Two minor PHP bugs filed today

First, set_error_handler() doesn’t return false if no previous handler was set but returns NULL.

Second, it’s not possible to restore the PHP original error_handler in PHP with set_error_handler().

I hope I did my research well, but as far as I could see, those two are correct according the current CVS code.

Add comment November 4th, 2005

Extending SimpleXML

Christian Stocker quoted Rob Richards from the PHP internals mailing list on how to extend SimpleXML. Someone needed more information of the structure of the XML document, for example the name of the node. On the list it was suggested to use the DOM extension which can, without too much overhead, import SimpleXML document (which can be re-imported to SimpleXML again).

The solution adviced on the list was to derive a class from SimpleXMLElement, pass this class to the simplexml_load_* function as second parameter.

Add comment November 1st, 2005

getParent patch for tidy

This is a small patch for current CVS HEAD in PHP which enables the tidy getParent() function which seemed to be forgotten.

Update on 24th of March, 2006: seems it’s necessary to ask the PHP developer with whom to sleep to get a patch finally commited.

Index: php_tidy.h
===================================================================
RCS file: /repository/php-src/ext/tidy/php_tidy.h,v
retrieving revision 1.25
diff -u -r1.25 php_tidy.h
--- php_tidy.h  25 Apr 2005 20:46:16 -0000      1.25
+++ php_tidy.h  15 Jul 2005 09:59:44 -0000
@@ -89,6 +89,7 @@
TIDY_NODE_METHOD(isJste);
TIDY_NODE_METHOD(isAsp);
TIDY_NODE_METHOD(isPhp);
+TIDY_NODE_METHOD(getParent);

ZEND_BEGIN_MODULE_GLOBALS(tidy)
char *default_config;
Index: tidy.c
===================================================================
RCS file: /repository/php-src/ext/tidy/tidy.c,v
retrieving revision 1.65
diff -u -r1.65 tidy.c
--- tidy.c      25 Apr 2005 20:46:16 -0000      1.65
+++ tidy.c      15 Jul 2005 09:59:45 -0000
@@ -291,6 +291,7 @@
TIDY_NODE_ME(isJste, NULL)
TIDY_NODE_ME(isAsp, NULL)
TIDY_NODE_ME(isPhp, NULL)
+       TIDY_NODE_ME(getParent, NULL)
{NULL, NULL, NULL}
};

@@ -1668,6 +1669,30 @@
}
/* }}} */

+/* {{{ proto boolean tidyNode::getParent()
+   Returns the parent node if available or NULL */
+TIDY_NODE_METHOD(getParent)
+{
+       TidyNode        parent_node;
+       PHPTidyObj *newobj;
+       TIDY_FETCH_ONLY_OBJECT;
+
+       parent_node = tidyGetParent(obj->node);
+       if(parent_node) {
+               tidy_instanciate(tidy_ce_node, return_value TSRMLS_CC);
+               newobj = (PHPTidyObj *) zend_object_store_get_object(return_value TSRMLS_CC);
+               newobj->node = parent_node;
+               newobj->type = is_node;
+               newobj->ptdoc = obj->ptdoc;
+               newobj->ptdoc->ref_count++;
+               tidy_add_default_properties(newobj, is_node TSRMLS_CC);
+       } else {
+               ZVAL_NULL(return_value);
+       }
+}
+/* }}} */
+
+
static void _php_tidy_register_nodetypes(INIT_FUNC_ARGS)
{
TIDY_NODE_CONST(ROOT, Root);

Add comment August 12th, 2005

Never trust user input, even not PHP_SELF

As Sean Coates points out, never trust user data any kind of. He gives a good example on what could slip the developers eye: the PHP_SELF variable. Read his blog for examples and how to cope with it.

Add comment May 24th, 2005

PHP upgrading fun with ob_gzhandler

For some people it’s fun upgrading php. For me it’s work. This time I had the pleasure of upgrading 4.2.2 to 4.3.9. Unfortunately it did break the behaviour of ob_gzhandler.

For some reason it was decided to modify the behaviour of ob_gzhandler when the client sends no Accept-Encoding header. Prior to this change, the function simple returned the data unmodified if it wasn’t able to detect any support encoding.

After this change, it simply returns false. So this is pretty bad when you use it this way

echo ob_gzhandler($data);

because now all you get back is a blank page.

What client does not send an accept encoding? As it seems some wierd Internet Explorer configration insisting to use the HTTP/1.0 protocol. Or wget. Now tell me this is something people verify nowadays when upgrading a server-side software?

Add comment April 6th, 2005

Previous Posts


Calendar

March 2010
M T W T F S S
« Jan    
1234567
891011121314
15161718192021
22232425262728
293031  

Posts by Month

Posts by Category