Welcome Guest, Not a member yet? Register   Sign In
What is the expected output of ini_set('display_errors', 0)?
#1

hi,

I'm in doubt about a fairly basic thing. CodeIgniter's standard index.php file, which I did not modify in any way, follows this general best practice:

switch (ENVIRONMENT)
{
   case 'development':
      error_reporting(-1);
      ini_set('display_errors'1);
   break;

   case 'testing':
   case 'production':
      ini_set('display_errors'0);


Indeed, we do not want to show detailed technical errors to users once we're in production. However, if any general error occurs, what exactly should the user see if display errors is disabled? I would expect that this...

 ini_set('display_errors'0);

Will not show error details to the user, however, it should show something. Currently, when I forcefully disable error display as above, I get a full 500 error in the browser (in Chrome showing that broken face icon) when forcing a runtime exception (for example PHP parse error or loading a model that does not exist).

Is this as expected? 

I would expect that error details are not exposed, yet CI should still show something of a generic "whoops" error page in this case. 

A 500 error can of course also be caused by config issues at Apache level, yet my setup generally works well and the Apache error log does not show any particular alternative causes. 

So my question: when display errors is disabled (as it should be in production) what will CI do when it encounters a runtime exception? What should it do? I'm trying to figure out if this is normal behavior (which would surprise me) or somehow I still do have some local problem in my setup.

Thanks for any help you can offer!
Reply
Reply
#3

Please note that ini_set(...) second parameter should be a string type 

Adding <?php declare('strict_types=1); at the start of the page will throw an error.

Check the PHP Online Manual:

https://www.php.net/manual/en/function.ini-set.php
Reply
#4

(09-08-2020, 07:19 AM)php_rocs Wrote: @ferdy,

Maybe these links can help you...
https://codeigniter.com/userguide3/gener...r-handling
https://codeigniter.com/userguide3/gener...-reporting

Thanks. I'm aware of those links but do not fully answer my question. Note this part:


Setting the ENVIRONMENT constant to a value of ‘development’ will cause all PHP errors to be rendered to the browser when they occur. Conversely, setting the constant to ‘production’ will disable all error output. Disabling error reporting in production is a good security practice.

My question remains: what should happen when disabling error output, yet an error occurs. What should the user see in that case?
Reply
#5

(09-08-2020, 10:40 PM)John_Betong Wrote: Please note that ini_set(...) second parameter should be a string type 

Adding <?php declare('strict_types=1); at the start of the page will throw an error.

Check the PHP Online Manual:

https://www.php.net/manual/en/function.ini-set.php

Thanks, John. Note that this code comes by default from CI 3. I did not change it in any way. You're absolutely right that ini_set should have a string parameter, yet it does not seem to change the situation. Allow me to explain by means of example error output:

[Image: PvsYILE.png]
The above is example output when intentionally triggering an error (loading a Model that does not exist) in 'development' mode. This corresponds to ini_set('display_errors', 1); as per standard CI3 logic.

This works fine. In development mode, we want to see these kind of technical error details. 

In production, we want to disable such output, so we do...

ini_set('display_errors', '0');

Keeping our intentional error in place (missing model) this is what the user will see:

[Image: KZbWSCe.png]

This is what my question is about. I understand not wanting to show technical error details to a user in production mode, but this shouldn't mean a user gets to see something like above, right?
Reply
#6

@ferdy,

Check out the source files. Htaccess file which from memory throws some error pages back to index.php.

Trapping the error 500 could also be modified to call index.php/error-500 assuming Pretty Urls have not been set.
Reply
#7

(09-09-2020, 10:01 AM)John_Betong Wrote: @ferdy,

Check out the source files. Htaccess file which from memory throws some error pages back to index.php.

Trapping the error 500 could also be modified to call index.php/error-500 assuming Pretty Urls have not been set.

Sorry, don't entirely understand what I should look for in .htaccess?

Any specific instructions on how to trap the 500 error?
Reply
#8

(This post was last modified: 09-09-2020, 04:23 PM by John_Betong.)

@ferdy,
I think that the program flow is:
1. htaccess is called first and decided what to do with URL
2. PHP index.php is called with any relevant URL parameters
3. PHP returns with a http_response(...) code, 200, 404, 500 etc
4. The htaccess script calls the ErrorDocument file if there is a match

This is the relevant CI4 .htaccess file (I'm typing on a tablet and have no access to the CI3 files)

PHP Code:
<IfModule !mod_rewrite.c>
    
# If we don't have mod_rewrite installed, all 404's
    # can be sent to index.php, and everything works as normal.
    
ErrorDocument 404 index.php
</IfModule

Edit:
Check the following link for a detailed explanation of how to handle PHP errors:

https://phpdelusions.net/articles/error_reporting
Reply
#9

Thanks, John. Just dropping a quick note that I appreciate the response. Have been distracted with other things but will look deeply into that article soon, try out some things, and report back.
Reply
#10

I finally had some time to study your answers and to read that excellent article.

To pinpoint the situation: we're in production and with an unchanged index.php, this means display errors is disabled. Next, a fatal error, exception or PHP parse error happens, something we're not catching/handling in our own code. What happens?

CodeIgniter registers all of these:

   set_error_handler('_error_handler');
   set_exception_handler('_exception_handler');
   register_shutdown_function('_shutdown_handler');


Therefore, it is in control of such unexpected errors, not Apache.

In all the error examples I gave, it will ultimately call "_error_handler" from Common.php, and here we see the heart of the matter:

// Should we display the error?
if (str_ireplace(array('off''none''no''false''null'), ''ini_get('display_errors')))
{
   $_error->show_php_error($severity$message$filepath$line);
}

exit(1); // EXIT_ERROR

As we are in production, the only thing CI will do in this case is to just exit the process. It will NOT show anything to the user.

I consider this an oversight of the framework. You always want to show something to the user. In production, you should not show the error itself or its stack trace, yet you will definitely want some generic branded error page.

CodeIgniter does not take this responsibility. Either it lets the web server handle it, or if it doesn't, just let the browser show a generic "crash" page, which is awful. Apache error documents do not work for all types of errors, they're sensitive and relying on configuration makes the application less portable. That's why I consider this a gap in the framework.

CodeIgniter is wrong to conclude that when display errors is disabled, it means the user should see nothing at all. You will always want to show something.

As unfortunately this behavior is defined in Common.php, I had to do this override there:

if (str_ireplace(array('off''none''no''false''null'), ''ini_get('display_errors')))
      {
         $_error->show_exception($exception);
      } else {
         $_error->show_exception_fallback($exception);
      }


In the "else" situation, we're in production with display errors off, and I'm calling a custom "show_exception_fallback" method, which is my own method defined in MY_Exceptions.php. That method shows a generic branded page to the user.
Reply




Theme © iAndrew 2016 - Forum software by © MyBB