Fork me on GitHub
漫笔 - 213  文章 - 13  trackbacks - 0
<2017年2月>
2930311234
567891011
12131415161718
19202122232425
2627281234
567891011


专心即时通讯及网游服务端编程
------------------------------------
Openresty之lua-nginx-module
------------------------------------
本博保藏大部分文章为转载,并在文章最初给出了原文出处,如有再转,敬请保存相关信息,这是我们对原创作者劳动成果的自觉尊重!!如为您带来不便利,请于本博下留言,谢谢合作。

常用链接

留言簿(1)

漫笔分类

漫笔档案

相册

Awesome

Blog

Book

GitHub

Link

查找

  •  

积分与排名

  • 积分 - 80548
  • 排名 - 250

最新谈论

阅览排行榜

PHP 注册过错和反常处理机制

注册过错和反常处理机制有三个PHP函数需求学习

1. register_shutdown_function('Bootstrap\Library\Frame::fatalError');

2. set_error_handler('Bootstrap\Library\Frame::appError');

3. set_exception_handler('Bootstrap\Library\Frame::appException');

1.register_shutdown_function 

界说:该函数是来注册一个会在PHP间断时履行的函数

参数阐明:

void register_shutdown_function ( callable $callback [, mixed $parameter [, mixed $... ]] )  

注册一个 callback ,它会在脚本履行完结或许 exit() 后被调用。

callback:待注册的间断回调

parameter:能够经过传入额定的参数来将参数传给间断函数

PHP间断状况有三种

履行完结

仿制代码
<?php   function test()   {       echo '这个是间断办法test的输出';   }      register_shutdown_function('test');      echo 'before' . PHP_EOL;    // => before   // => 这个是间断办法test的输出  
仿制代码

留意输出的次序,等履行完结了之后才会去履行register_shutdown_function的间断办法test  

exit/die导致的间断

仿制代码
<?php   function test()   {       echo '这个是间断办法test的输出';   }      register_shutdown_function('test');      echo 'before' . PHP_EOL;   exit();   echo 'after' . PHP_EOL;    // => before // => 这个是间断办法test的输出  
仿制代码

后边的after并没有输出,即exit或许是die办法导致提早间断。

发作丧命过错间断

仿制代码
<?php   function test()   {       echo '这个是间断办法test的输出';   }      register_shutdown_function('test');      echo 'before' . PHP_EOL;      // 这里会发作丧命过错   $a = new a();      echo 'after' . PHP_EOL;    // => before // => Fatal error: Uncaught Error: Class 'a' not found in D:\laragon\www\php_book\test.php on line 12 // => Error: Class 'a' not found in D:\laragon\www\php_book\test.php on line 12   // => Call Stack:   // => 0.0020     360760   1. {main}() D:\laragon\www\php_book\test.php:0   // => 这个是间断办法test的输出
仿制代码

后边的after也是没有输出,丧命过错导致提早间断了。

参数:第一个参数支撑以数组的方式来调用类中的办法,第二个以及后边的参数都是能够作为额定的参数传给间断办法。

仿制代码
<?php      class Shutdown   {       public function stop()       {           echo "这个是stop办法的输出";       }   }      // 当PHP间断的时分(履行完结或许是遇到丧命过错间断的时分)会调用new Shutdown的stop办法   register_shutdown_function([new Shutdown(), 'stop']);      // 将由于丧命过错而间断   $a = new a();      // 这一句并没有履行,也没有输出   echo '有必要间断';  
仿制代码

也能够在类中履行:

仿制代码
<?php      class TestDemo {       public function __construct()       {           register_shutdown_function([$this, "f"], "hello");       }          public function f($str)       {           echo "class TestDemo->f():" . $str;       }   }      $demo = new TestDemo();   echo 'before' . PHP_EOL;      /**  运转:  before  class TestDemo->f():hello   */  
仿制代码
能够屡次调用 register_shutdown_function,这些被注册的回调会依照他们注册时的次序被顺次调用。
不过留意的是,假如在第一个注册的间断办法里边调用exit办法或许是die办法的话,那么其他注册的间断回调也不会被调用。
代码:
仿制代码
<?php   /**   * 能够屡次调用 register_shutdown_function,这些被注册的回调会依照他们注册时的次序被顺次调用。   * 留意:假如你在f办法(第一个注册的办法)里边调用exit办法或许是die办法的话,那么其他注册的间断回调也不会被调用   */      /**   * @param $str   */   function f($str) {       echo $str . PHP_EOL;          // 假如下面调用exit办法或许是die办法的话,其他注册的间断回调不会被调用       // exit();   }      // 注册第一个间断回调f办法   register_shutdown_function("f", "hello");      class TestDemo {       public function __construct()       {           register_shutdown_function([$this, "f"], "hello");       }          public function f($str)       {           echo "class TestDemo->f():" . $str;       }   }      $demo = new TestDemo();   echo 'before' . PHP_EOL;      /**  运转:  before  hello  class TestDemo->f():hello    留意:假如f办法里边调用了exit或许是die的话,那么最终的class TestDemo->f():hello不会输出   */  
仿制代码
该函数的效果:
  • 析构函数:在PHP4的时分,由于类不支撑析构函数,所以这个函数常常用来模仿完结析构函数
  • 丧命过错的处理:运用该函数能够用来捕获丧命过错并且在发作丧命过错后康复流程处理

代码如下:

仿制代码
<?php   /**   * register_shutdown_function,注册一个会在php间断时履行的函数,间断的状况包括发作丧命过错、die之后、exit之后、履行完结之后都会调用register_shutdown_function里边的函数   * Created by PhpStorm.   * User: Administrator   * Date: 2017/7/15   * Time: 17:41   */      class Shutdown   {       public function stop()       {           echo 'Begin.' . PHP_EOL;           // 假如有发作过错(一切的过错,包括丧命和非丧命)的话,获取最终发作的过错           if (error_get_last()) {               print_r(error_get_last());           }              // ToDo:发作丧命过错后康复流程处理              // 间断后边的一切处理           die('Stop.');       }   }      // 当PHP间断的时分(履行完结或许是遇到丧命过错间断的时分)会调用new Shutdown的stop办法   register_shutdown_function([new Shutdown(), 'stop']);      // 将由于丧命过错而间断   $a = new a();      // 这一句并没有履行,也没有输出   echo '有必要间断';  
仿制代码
仿制代码
Fatal error: Uncaught Error: Class 'a' not found in D:\laragon\www\php_book\1_23_register_shutdown.php on line 31      Error: Class 'a' not found in D:\laragon\www\php_book\1_23_register_shutdown.php on line 31      Call Stack:       0.0060     362712   1. {main}() D:\laragon\www\php_book\1_23_register_shutdown.php:0      Begin.   Array   (       [type] => 1       [message] => Uncaught Error: Class 'a' not found in D:\laragon\www\php_book\1_23_register_shutdown.php:31   Stack trace:   #0 {main}     thrown       [file] => D:\laragon\www\php_book\1_23_register_shutdown.php       [line] => 31   )   Stop.  
仿制代码

留意:PHP7中新增了Throwable反常类,这个类能够捕获丧命过错,即能够运用try...catch(Throwable $e)来捕获丧命过错,代码如下:

仿制代码
<?php      try {       // 将由于丧命过错而间断       $a = new a();          // 这一句并没有履行,也没有输出       echo 'end';   } catch (Throwable $e) {       print_r($e);       echo $e->getMessage();   }  
仿制代码

运转:

仿制代码
Error Object   (       [message:protected] => Class 'a' not found       [string:Error:private] =>       [code:protected] => 0       [file:protected] => C:\laragon\www\php_book\throwable.php       [line:protected] => 5       [trace:Error:private] => Array           (           )          [previous:Error:private] =>       [xdebug_message] =>   Error: Class 'a' not found in C:\laragon\www\php_book\throwable.php on line 5      Call Stack:       0.0000     349856   1. {main}() C:\laragon\www\php_book\throwable.php:0      )   Class 'a' not found  
仿制代码
这样的话,PHP7中运用Throwable来捕获的话比运用register_shutdown_function这个函数来得更便利,也更引荐Throwable。
留意:Error类也是能够捕获到丧命过错,不过Error只能捕获丧命过错,不能捕获反常Exception,而Throwable是能够捕获到过错和反常的,所以更引荐。
 
总结:register_shutdown_function这个函数主要是用在处理丧命过错的后续处理上(PHP7更引荐运用Throwable来处理丧命过错),不过缺陷也很明显,只能处理丧命过错Fatal error,其他的过错包括最高过错Parse error也是没办法处理的。
 

 

 

2.set_error_handler

经过 set_error_handler() 函数设置用户自界说的过错处理程序,然后触发过错(经过 trigger_error()):

仿制代码
<?php  // 用户界说的过错处理函数  function myErrorHandler($errno, $errstr, $errfile, $errline) {      echo "<b>Custom error:</b> [$errno] $errstr<br>";      echo " Error on line $errline in $errfile<br>";  }   // 设置用户界说的过错处理函数  set_error_handler("myErrorHandler");   $test=2;   // 触发过错  if ($test>1) {      trigger_error("A custom error has been triggered");  }  ?> 
仿制代码

以上代码的输出相似这样:

Custom error: [1024] A custom error has been triggered  Error on line 14 in C:\webfolder\test.php

界说和用法

set_error_handler() 函数设置用户界说的过错处理函数。

注释:假如运用该函数,会绕过规范 PHP 过错处理程序,一同假如必要,用户界说过错程序经过 die() 间断脚本。

注释:假如过错发作在脚本履行之前(比方文件上传时),将不会调用自界说的过错处理程序由于它没有在那时注册。

语法

set_error_handler(errorhandler,E_ALL|E_STRICT);
参数描绘
errorhandler必需。规则用户过错处理函数的称号。
E_ALL|E_STRICT可选。规则显现何种过错报告等级的用户界说过错。默许是 "E_ALL"。

技能细节

回来值:包括之前界说的过错处理程序的字符串。
PHP 版别:4.0.1+
PHP 更新日志:

PHP 5.5:参数 errorhandler 现在承受 NULL

PHP 5.2: 过错处理程序有必要回来 FALSE 来显现 $php_errormsg。

3.set_exception_handler

设置用户界说的反常处理函数:

仿制代码
<?php // 用户界说的反常处理函数  function myException($exception) {      echo "<b>Exception:</b> ", $exception->getMessage();  }   // 设置用户界说的反常处理函数  set_exception_handler("myException");  // 抛出反常 throw new Exception("Uncaught exception occurred!");  ?> 
仿制代码

以上代码的输出相似这样:

Exception: Uncaught exception occurred!

界说和用法

set_exception_handler() 函数设置用户界说的反常处理函数。

脚本会在此反常处理程序被调用后间断履行。

语法

set_exception_handler(exceptionhandler);
参数描绘
exceptionhandler

必需。规则当一个未捕获的反常发作时所调用函数的称号。

注释:也能够传递一个 NULL 值用于重置反常处理函数为默许值。

技能细节

回来值:

回来包括之前界说的反常处理程序的称号的字符串,或许在过错时回来 NULL。

假如之前没有界说一个过错处理程序,也会回来 NULL。

假如参数运用了 NULL,重置处理程序为默许状况,并且会回来一个 TRUE。

PHP 版别:5.0+
PHP 更新日志:

PHP 7.0.0:传递到 exception_handler 中的参数类型从 Exception 更改为 Throwable。

PHP 5.5:之前,假如传递 NULL,该函数回来 TRUE。从 PHP 5.5 起回来之前的处理程序。

 

原创文章请随意转载。愿和我们共享,并且一同前进。-- 江 coder

C#中unhandled反常处理的问题

为了增强现在正在开发的体系的健壮性,需求捕获运转时呈现的无法意料并且没有被处理(unhandled)的反常。查了材料后,找到了运用 Application.ThreadException 事情处理这些反常的办法,底子过程包括, 
1、为ThreadException事情增加一个处理反常的函数句柄 
2、界说处理反常的函数 
比如如下: 
[STAThread] 
static
void Main() {   Application.ThreadException += new ThreadExceptionEventHandler(Application_ThreadException);   Application.Run(new FrmMain()); } private static void Application_ThreadException(object sender, ThreadExceptionEventArgs e) {   MessageBox.Show("Unhandled exception: "+e.Exception.ToString()); }
这种办法简单易行,并且处理功率较高,能够依照用户的目的,很便利的增加处理反常理的其他功用。但我发现,假如运用第三方供给的控件时,底子不起效果,原应可能是第三方控件运转在不同的线程中。在Microsoft的协助中也的确提到了,上面的办法只能处理主线程中未处理的反常。好了,上网查,找到了下面的办法,运用 AppDomain.UnhandledException 代替Application.ThreadException
首要需求了解的是,此刻界说的事情处理函数需求在抛出反常的线程中履行,但是在主线程中给出反常提示都是在主线程中完结的,那么怎么处理这个问题呢?下面的代码给出了一个比较完好的处理方案。
 
private delegate void ExceptionDelegate(Exception x);

static private FrmMain _MainForm;

///
<summary>
///
The main entry point for the application.
/// </summary>
[STAThread]
static
void Main()
{
  _MainForm = new FrmMain();
  AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(AppDomain_UnhandledException);
  Application.Run(_MainForm);
}

private static void AppDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
{
  Exception exception;

  exception = e.ExceptionObject as Exception;
  if (exception == null)
{
// this is an unmanaged exception, you may want to handle it differently
   return;
}
  PublishOnMainThread(exception);
}

private static void PublishOnMainThread(Exception exception)
{
  if (_MainForm.InvokeRequired)
  {
    // Invoke executes a delegate on the thread that owns _MainForms's underlying window handle.
    _MainForm.Invoke(new ExceptionDelegate(HandleException), new object[] {exception});
  }
  else
  {
    HandleException(exception);
  }
}

private static void HandleException(Exception exception)
{
  if (SystemInformation.UserInteractive)
  {
    using (ThreadExceptionDialog dialog = new ThreadExceptionDialog(exception))
    {
      if (dialog.ShowDialog() == DialogResult.Cancel)
        return;
    }
    Application.Exit();
    Environment.Exit(0);
  }
}

private void ThreadMethod()
{
  throw new Exception("From new thread");
}

private void button1_Click(object sender, System.EventArgs e)
{
  Thread thread;
  thread = new Thread(new ThreadStart(ThreadMethod));
  thread.Start();
}
需求留意的是:
1、需求为一切的 AppDomain 的 UnhandledException 增加一个处理
2、 UnhandledExceptionEventArgs 参数中包括一个 IsTerminating 特点,表明是否间断 common language runtime 

posted on 2018-08-03 17:43 思月行云 阅览(54) 谈论(0)  修改 保藏 引证 所属分类: PHP