rfc:engine_exceptions

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revisionPrevious revision
Next revision
Previous revision
rfc:engine_exceptions [2013/10/24 16:37] – a few small improvements nikicrfc:engine_exceptions [2017/09/22 13:28] (current) – external edit 127.0.0.1
Line 2: Line 2:
   * Date: 2013-10-23   * Date: 2013-10-23
   * Author: Nikita Popov <nikic@php.net>   * Author: Nikita Popov <nikic@php.net>
-  * Status: In Draft+  * Status: Declined for 5.6
   * Proposed for: PHP 5.6   * Proposed for: PHP 5.6
   * Patch: https://github.com/nikic/php-src/compare/engineExceptions   * Patch: https://github.com/nikic/php-src/compare/engineExceptions
 +  * ML discussion: http://markmail.org/message/uemuxsk3vk46nedo
  
 ===== Introduction ===== ===== Introduction =====
Line 10: Line 11:
 This RFC proposes to allow the use of exceptions in the engine and to allow the replacement of existing fatal or recoverable fatal errors with exceptions. This RFC proposes to allow the use of exceptions in the engine and to allow the replacement of existing fatal or recoverable fatal errors with exceptions.
  
-As an example of this change, consider the following the following code-snippet:+As an example of this change, consider the following code-snippet:
  
 <code php> <code php>
Line 123: Line 124:
  
 <code php> <code php>
-$lock->aquire();+$lock->acquire();
 try { try {
     doSomething();     doSomething();
Line 142: Line 143:
     public function __construct(Lock $lock) {     public function __construct(Lock $lock) {
         $this->lock = $lock;         $this->lock = $lock;
-        $this->lock->aquire();+        $this->lock->acquire();
     }     }
     public function __destruct() {     public function __destruct() {
Line 150: Line 151:
  
 function test($lock) { function test($lock) {
-    $manager = new LockManager($lock); // aquire lock+    $manager = new LockManager($lock); // acquire lock
          
     doSomething();     doSomething();
Line 255: Line 256:
 Currently it is possible to silently ignore recoverable fatal errors with a custom error handler. By replacing them with exceptions this capability is removed, thus breaking compatibility. Currently it is possible to silently ignore recoverable fatal errors with a custom error handler. By replacing them with exceptions this capability is removed, thus breaking compatibility.
  
-I have never seen this possibility used in practice outside some weird hacks (which use ignored recoverable type constraint errors to implement scalar typehints). In most cases custom error handlers throw an ''ErrorException'', in which case it emulates the proposed behavior but using a different exception type.+I have never seen this possibility used in practice outside some weird hacks (which use ignored recoverable type constraint errors to implement scalar typehints). In most cases custom error handlers throw an ''ErrorException'', i.e. they emulate the proposed behavior with a different exception type.
  
 If these concerns are considered significant this RFC might be restricted to ''E_ERROR'' conversions only. Personally I doubt that this will result in any significant breakage, but I can't claim extensive knowledge in this area. If these concerns are considered significant this RFC might be restricted to ''E_ERROR'' conversions only. Personally I doubt that this will result in any significant breakage, but I can't claim extensive knowledge in this area.
Line 261: Line 262:
 ==== catch-all blocks in existing code ==== ==== catch-all blocks in existing code ====
  
-As ''EngineException'' extends ''Exception'' it will be caught by catch-blocks of type ''catch (Exception)''. This may cause to cause existing code to inadvertantly catch engine exceptions.+As ''EngineException'' extends ''Exception'' it will be caught by catch-blocks of type ''catch (Exception)''. This may cause existing code to inadvertently catch engine exceptions.
  
-If this is considered to be an issue solution is to introduce a ''BaseException'' with ''Exception extends BaseException'', which will be the new base of the exception hierarchy. This exception type would be used only for exception types that are "unlikely to require catchingin anything save top-level handlers. Both Python (''BaseException'') and Java (''Throwable'') make use of this concept.+If this is considered to be an issue one possible solution is to introduce a ''BaseException'' with ''Exception extends BaseException'', which will be the new base of the exception hierarchy. Only exceptions that are considered unlikely to require catching in anything save top-level handlers will directly inherit from this type. Both Python (''BaseException'') and Java (''Throwable'') make use of this concept.
  
 ''EngineException'' could then extend ''BaseException'' rather than ''Exception''. ''EngineException'' could then extend ''BaseException'' rather than ''Exception''.
Line 297: Line 298:
 </code> </code>
  
-Additional improvement (like removing the ''Fatal error:'' prefix and the duplicate file/line information would require special handling in ''zend_error'':+Additional improvement (like removing the ''Fatal error:'' prefix and the duplicate file/line informationwould require special handling in ''zend_error'':
  
 <code> <code>
Line 305: Line 306:
 #1 {main} #1 {main}
 </code> </code>
 +
 +==== Not all errors converted ====
 +
 +The Zend Engine currently (master on 2013-12-10) contains the following number of fatal-y errors:
 +
 +<code>
 +E_ERROR:            183    (note: not counting 538 occurrences in zend_vm_execute.h)
 +E_CORE_ERROR:        12
 +E_COMPILE_ERROR:    151
 +E_PARSE:              1
 +E_RECOVERABLE_ERROR: 14
 +</code>
 +
 +The count was obtained using ''git grep "error[^(]*(E_ERROR_TYPE" Zend | wc -l'' and as such may not be totally accurate, but should be a good approximation.
 +
 +The patch attached to the RFC currently (as of 2013-10-24) removes 70 ''E_ERROR''s and 11 ''E_RECOVERABLE_ERROR''s. While I hope to port more errors to exceptions before the patch is merged, the process is rather time consuming and I will not be able to convert all errors. (Note: The number of occurrences in the source code says rather little about what percentage of "actually thrown" errors this constitutes.)
 +
 +Some errors are easy to change to exceptions, others are more complicated. Some are impossible, like the memory limit or execution time limit errors. The ''E_CORE_ERROR'' type can't be converted to use exceptions because it occurs during startup (at least if used correctly). ''E_COMPILE_ERROR'' (and ''E_PARSE'') currently also can't be converted to exceptions, due to concerns regarding global state modifications.
 +
 +Converting most existing errors will take some time and in the meantime we'll be in a situation where some part of the errors were converted to exceptions but another part stays fatal. From a user perspective it may not be immediately clear when one is used over the other.
 +
 +While this may be slightly inconvenient, I strongly think that it's better to start fixing this gradually, rather than waiting until the time (that will never come) where we can fix everything at once.
 +
 +===== Backwards compatibility =====
 +
 +The ''E_ERROR'' portion of this proposal does not break backwards compatibility: All code that was previously working, will continue to work. The change only relaxes error conditions, which is generally not regarded as breaking BC.
 +
 +The ''E_RECOVERABLE_ERROR'' part of the proposal may introduce a minor BC break, because it will no longer allow to silently ignore recoverable errors with a custom error handler. As this point is somewhat controversial I'll have a separate voting option for this.
  
 ===== Patch ===== ===== Patch =====
Line 310: Line 339:
 A preliminary patch for this RFC is available at https://github.com/nikic/php-src/compare/engineExceptions. A preliminary patch for this RFC is available at https://github.com/nikic/php-src/compare/engineExceptions.
  
-The patch introduces basic infrastructure for this change and removes all ''E_ERROR'' uses from ''zend_vm_def.h'' (as well as some other errors). This is just preliminary work and hopefully more errors can be covered by the time this is merged.+The patch introduces basic infrastructure for this change and removes all ''E_ERROR'' uses from ''zend_vm_def.h'' (as well as some other errors). 
 + 
 +===== Vote ===== 
 + 
 +This is a yes/no vote with the additional option of implementing the proposal, but without changing ''E_RECOVERABLE_ERROR''s (as that part of the proposal may have BC issues). 
 + 
 +As this is a language-related change, the vote requires a two-third majority. The 3-way vote will be interpreted as follows: If 2/3 of the total votes are for "Yes", the proposal is implemented fully. If 2/3 of the votes are for "Yes" or "Yes, without E_RECOVERABLE_ERROR changes" then the proposal is implemented without the ''E_RECOVERABLE_ERROR'' changes. Otherwise, the proposal is not implemented. 
 + 
 +If you are in favor of this proposal in general, but not for PHP 5.6, use the "No" voting option. 
 + 
 +<doodle title="Implement in PHP 5.6?" auth="nikic" voteType="single" closed="true"> 
 +   * Yes 
 +   * Yes, without E_RECOVERABLE_ERROR changes 
 +   * No 
 +</doodle> 
 + 
 +Vote started on 2013-12-07 and ended on 2013-12-14.
rfc/engine_exceptions.1382632654.txt.gz · Last modified: 2017/09/22 13:28 (external edit)