Skip to content
Advertisement

ob_get_status() has undocumented bits set in ‘flags’ entry

I’m having an issue with an output buffer not being called at the end of my PHP application.

If I call get_ob_status(true) just before my script ends, I get the following output:

Array
(
    [0] => Array
        (
            [name] => FatalErrorHandler
            [type] => 1
            [flags] => 113
            [level] => 0
            [chunk_size] => 0
            [buffer_size] => 32768
            [buffer_used] => 32058
        )

    [1] => Array
        (
            [name] => RequestLogger
            [type] => 1
            [flags] => 12401
            [level] => 1
            [chunk_size] => 0
            [buffer_size] => 0
            [buffer_used] => 0
        )

)

The outer buffer looks broadly as I would expect, but there are two things that are odd about the inner buffer:

  1. It is empty (everything has already dropped-through to the outer buffer). I am not aware of anything in my code that would cause this as there are no explicit flushes happening. Why is it being bypassed?

  2. The ‘flags’ attribute contains a weird, undocumented value: 12401. Bits 1, 5, 6 and 7 are documented: The first bit indicates the buffer state (PHP_OUTPUT_HANDLER_START) whilst the others indicate the flags set by ob_start() (i.e. that the buffer is flushable, cleanable and deletable). However, bits 13 and 14 are also set, and as far as I can see, these are completely undocumented.

Both buffers were created using ob_start("FunctionName") with no other arguments. I should also note that there are no issues in PHP 5.3, where everything works as expected and the output of ob_get_status() shows exactly what I would expect to see. I am aware that the output buffering appears to have had a major rewrite in PHP 5.4, which probably accounts for this.

What do these undocumented flags mean, and do they give any indication about why the output buffer is being skipped?

Advertisement

Answer

I can’t answer why the buffer is empty, but I can point you in the direction of the missing flags: https://github.com/php/php-src/blob/a1a8e9032c496c060767d1bba6eebdcf6c935d25/main/php_output.h#L41

/* handler status flags */
#define PHP_OUTPUT_HANDLER_STARTED      0x1000
#define PHP_OUTPUT_HANDLER_DISABLED     0x2000
#define PHP_OUTPUT_HANDLER_PROCESSED    0x4000

You can see these used around here: https://github.com/php/php-src/blob/90b7bde61507cee1c6b37f153909d72f5b203b8c/main/output.c#L1008

    switch (status) {
        case PHP_OUTPUT_HANDLER_FAILURE:
            /* disable this handler */
            handler->flags |= PHP_OUTPUT_HANDLER_DISABLED;

A bug has been filed (go all the way to the end) from a documentation-perspective, but it doesn’t appear anyone has done anything with it yet.

You can easily reproduce the flags (if you ever want to) using:

ob_start();
ob_flush();

var_dump(ob_get_status(true));

Which should give you:

array(1) {
  [0]=>
  array(7) {
    ["name"]=>
    string(22) "default output handler"
    ["type"]=>
    int(0)
    ["flags"]=>
    int(20592)
    ["level"]=>
    int(0)
    ["chunk_size"]=>
    int(0)
    ["buffer_size"]=>
    int(16384)
    ["buffer_used"]=>
    int(0)
  }
}

Your specific code appears to be PHP_OUTPUT_HANDLER_STARTED | PHP_OUTPUT_HANDLER_DISABLED

User contributions licensed under: CC BY-SA
1 People found this is helpful
Advertisement