Jump to content

Sending output to browser before headers... why DID it work?


Recommended Posts

I just got this message when I moved a new, supposedly debugged version of software to my client's staging site:

 

Cannot send session cache limiter - headers already sent...

 

I found the problem without a lot of difficulty: an included file was sending JavaScript code to the browser before a call to session_start(). It's not clear to me why session_start sets a cache limiter, but apparently it does.

 

My question is why this problem did not appear on my development system. The same code was executed there; it presumably tried to do the same thing, and did so after the JavaScript was sent. Yet everything worked perfectly. That's bad behavior; if it's going to fail on the staging site (or the production site!) I want to to fail when I'm deugging.

My guess would be that your development box doesn't have error reporting set at a high enough level, display_errors is Off, or it's set up to use output buffering by default via the output_buffering directive in the php.ini file.

My guess would be that your development box doesn't have error reporting set at a high enough level..

 

Not that. Each script includes a common file that sets it to E_STRICT+E_NOTICE on both systems.

 

...display_errors is Off...

 

Not that either. I get error notices when I expect them... except in this case. I checked phpinfo and it confirms that the setting is on.

 

...or it's set up to use output buffering by default via the output_buffering directive in the php.ini file.

 

For a while I thought this was it. php_info reported that output_buffering is "no value" on the staging system, and 4096 on my development system. But I set it to "off" on the development system through .htacess, and init_get() confirms that it is "off," but my script still doesn't get the error.

 

Maybe "no value" has a different effect than "off." I haven't previously encountered a "no value" value, and I don't know how to set it, so I can't test that theory!

 

I think you've got me on the right trail, but the quarry is not yet in sight.

; By default, PHP is set to take action on all errors, notices and warnings EXCEPT

; those related to E_NOTICE and E_STRICT, which together cover best practices and

; recommended coding standards in PHP. For performance reasons, this is the

; recommend error reporting setting. Your production server shouldn't be wasting

; resources complaining about best practices and coding standards. That's what

; development servers and development settings are for.

; Note: The php.ini-development file has this setting as E_ALL | E_STRICT. This

; means it pretty much reports everything which is exactly what you want during

; development and early testing.

 

 

; E_NOTICE          - run-time notices (these are warnings which often result

;                    from a bug in your code, but it's possible that it was

;                    intentional (e.g., using an uninitialized variable and

;                    relying on the fact it's automatically initialized to an

;                    empty string)

; E_STRICT          - run-time notices, enable to have PHP suggest changes

;                    to your code which will ensure the best interoperability

;                    and forward compatibility of your code

 

I would suggest changing your runtime settings (common file) to E_ALL.

I tried setting E_ALL and E_STRICT|E_ALL. Neither one got me messages.

 

(I also found a dumb error: I was setting the error reporting level after the point where the error occurred. I'm glad I found that, but fixing it didn't help.)

 

I've got a nagging feeling that there's some missing piece to this puzzle, but I don't know what it is. I'm attaching phpInfo dumps from my development system and the staging system, in case they suggest something to you.

 

[attachment deleted by admin]

If your code works on your development system, then output_buffering must be on at some point. I.E. even if the error_reporting/display_errors are set to hide errors, the output would still be occurring and stop the session_start from working.

 

Your error_reporting on both systems is definitely not E_ALL (or even better a -1).

I wrote this script to isolate the problem:

 

<?php
error_reporting(-1);
$buffering = "output_buffering=" . ini_get('output_buffering') . "<br/>";
$buffering .= "error_reporting=" . ini_get('error_reporting') . "<br/>";
$buffering .= "display_errors=" . ini_get('display_errors') . "<br/>";
$buffering .= "<br/>1:";
$buffering .= isset($_SESSION) ? var_export($_SESSION,true) : "_SESSION not set<br/>";

session_start();

echo "Session started</br>\n";
echo $buffering;
echo "<br/>2:"; var_dump($_SESSION);
?>

Here's its output:

 

Session started

output_buffering=off

error_reporting=-1

display_errors=1

 

1:_SESSION not set

 

2:

 

array

  empty

 

I examined the page source to see if there were extra spaces before the intended output. There were not.

 

Then I added the following line before the call to session_start:

 

echo "Session not yet started<br/>";

 

Here's the output:

 

Session not yet started

Session started

output_buffering=off

error_reporting=-1

display_errors=1

 

1:_SESSION not set

 

2:

 

array

  empty

 

Still no errors. I'm not saying you're wrong, but I don't understand how to reconcile these results with what you're saying.

 

One other thing puzzles me about this: I thought that session_start set $_SESSION['LAST_ACTIVITY'], but it's not there. Maybe that's it doesn't get set until the cookie is written, and this is normal.

If your session_start() statement did not produce an error message (like the error in the first post in this thread) when you echoed something before it, then either the error_reporting/display_errors or the output_buffering settings are not actually what are being shown (php has had a history of displaying settings that it is not actually using.)

 

In the same code, try to cause php errors. Add something like the following to see if you get any error messages -

echo $i_dont_exist;

Roger that. I added the line

 

$buffering .= $imaginary;

 

before the line that calls isset(), and I got this (with nice colors and formatting that didn't survive cut and paste):

 

 

( ! ) Notice: Undefined variable: imaginary in D:\htdocs\login\sessionbug.php on line 7

Call Stack

# Time Memory Function Location

1 0.0038 60784 {main}( ) ..\sessionbug.php:0

Session not yet started

Session started

output_buffering=off

error_reporting=-1

display_errors=1

 

1:_SESSION not set

 

2:

 

array

  empty

 

It really does appear to be displaying errors.

PFMaBiSmAd: I appreciate your efforts to help me so far, but I wonder what is happening now. Your earlier responses came within hours, but I've waited a couple of days for your response to my last post.

 

If you're out of ideas or time, please let me know so that I can look elsewhere. If not, I'm happy to wait, but I'd like to confirm that I'm waiting for something that's going to happen!

I didn't see that your reply #8 had been posted (sometimes the SMF software doesn't show all posts when you click the "show unread posts since your last visit" link.)

 

Are you actually using a web server on your localhost development system? It would appear that you are using some IDE or debugger and one or both of them could be causing the unexplained symptoms (in fact most debuggers work by manipulating the actual code that is executing and using output buffering to capture the debugging output.)

I'm doing most of my work with NetBeans and XDebug. XDebug displays page output by opening a new tab in an independent browser, in my case Firefox 4.0.

 

It was appealing to think that the pages are acting weird because I'm running my scripts in the debugger, but it turned out not to be so. I tried running my current test code on my development system without the debugger, and still got no errors. I uploaded the same code to the staging server and got the same old errors!

This thread is more than a year old. Please don't revive it unless you have something important to add.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.