An in-depth understanding of the abnormal mechanism of PHP principles

Source: Internet
Author: User
What is the ZEND_HANDLE_EXCEPTION at the end of every oparray that can be executed independently in PHP? What is the principle of the PHP exception mechanism?
What is the ZEND_HANDLE_EXCEPTION at the end of each op array that can be executed independently in PHP?
Let's start with a question. last week, blue5tar raised a question: "For the following code, onError is executed, but onException is not executed. why ?".

The code is as follows:


Function onError ($ errCode, $ errMesg, $ errFile, $ errLine ){
Echo "Error Occurred \ n ";
Throw new Exception ($ errMesg );
}
Function onException ($ e ){
Echo $ e-> getMessage ();
}
Set_error_handler ("onError ");
Set_exception_handler ("onException ");
/* I will never name the file with my name, so this file does not exist */
Require ("laruence. php ");


Running result:

The code is as follows:


Error Occurred
PHP Fatal error: main (): Failed opening required' laruence. php


First, we need to know that when Require contains a problem that cannot be found, two errors will be thrown before and after Require,

The code is as follows:


WARNING: thrown when PHP tries to open this file.
E_COMPILE_ERROR: thrown after the function of opening the file from PHP fails to return


As we know, set_error_handler cannot catch E_COMPILE_ERROR:
The following error types cannot be handled with a user defined function: E_ERROR, E_PARSE, E_CORE_ERROR, E_CORE_WARNING, E_COMPILE_ERROR, E_COMPILE_WARNING, and most of E_STRICT raised in the file where found () is called.
Therefore, in onError, only the first WARNING error can be caught, but the exception thrown in onError is not caught by the default exception_handler?
Let's talk about the abnormal mechanism of PHP.
Everyone familiar with opcode (Opcodes, who has a deep understanding of PHP principles, knows that before PHP5.3, the last opcode of every independently running op array (File, function, method) was ZEND_HANDLE_EXCEPTION, what is the opcode used?
In PHP, when an exception is throw, it will jump to the last line of each op array to execute this ZEND_HANDLE_EXCEPTION. the pseudo code is as follows:

The code is as follows:


Void on_throw_exception (zval * exception TSRMLS_DC ){
1. determine whether an exception has been thrown
2. record exception
3. record the sequence number of the next op line to be executed
4. the next op line number to be executed = the last one of the current op array
}


Well, just like rewriting the ip register, rewriting the serial number of the next op line to be executed changes the flow of the program. in this way, it enters the processing logic of ZEND_HANDLE_EXCEPTION.
In ZEND_HANDLE_EXCEPTION, it determines whether the exception is in try catch,

The code is as follows:


If yes, set the next op line to be executed as the op line of the first catch and continue execution.
If not, destroy unnecessary variables and opline and directly end the execution process.


Some may ask: "When will the default processing function (user_exception_handler) take effect for the exception set by set_exception_handler ?"
Well, it is only after the execution is complete and exit the execution LOOP to determine whether there is a default exception handling function. If yes, it is called:

The code is as follows:


// Execute
Zend_execute (EG (active_op_array) TSRMLS_CC );
If (EG (exception )){
If (EG (user_exception_handler )){
Call the user-defined default exception handling function
} Else {
Uncaptured exceptions
}
} Else {
No exception
}
Destroy_op_array (EG (active_op_array) TSRMLS_CC );
Efree (EG (active_op_array ));



PHP exception process

Note: One of the points in the figure is not rigorous, that is, when determining whether the last catch block is used, it will be judged at the same time (is_a). if so, it will be executed in the last catch block.
When PHP encounters a Fatal Error, zend_mongolout is directly used, and zend_mongolout causes the program process to directly skip the above code segment. It can also be understood as directly exit (longjmp ), this leads to the failure of user_exception_handler.
After learning about this, why do I want to start with the article? Is that clear?
Finally, you may have some questions about ZEND_HANDLE_EXCEPTION: if so, why does the ZEND_HANDLE_EXCEPTION exist at the end of every independently executed op array? In the simplest way, if a function does not throw, this opcode is obviously unnecessary? Hey, you are very smart. PHP 5.3 has already been adjusted according to your ideas. ZEND_HANDLE_EXCEPTION opline will be generated dynamically only at the throw moment.
PHP5 changelog:
Changed exception handling. Now each op_array doesn't contain ZEND_HANDLE_EXCEPTION opcode in the end. (Dmitry)

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.