如何捕捉panic

本文介绍了一种在程序中捕获不可恢复panic的方法,通过在独立线程中运行测试案例,利用RThread::Logon()和RThread::ExitReason()监测线程状态,确保即使发生严重错误,测试框架仍能继续运行。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

收藏
How to catch a panic

http://wiki.forum.nokia.com/index.php/How_to_catch_a_panic

http://wiki.forum.nokia.com/index.php/%E5%A6%82%E4%BD%95%E6%8D%95%E6%8D%89panic

From Forum Nokia Wiki
Yes, a panic. Although panics, by their nature, are uncatchable there is a way to prevent them from severely influencing your program.

First off, why would you do it? What is the use-case? Typically a panic draws attention to a programmatic error that should have already been corrected in the program. It always terminates the program execution and it's on purpose: programs panic from an unrecoverable stage. So why would we want to catch a panic if we were able to do so?

Well, there is at least one special use-case: in a test framework used for automated testing. In a typical unit testing framework, for example, where test suites containing test cases are being performed it's always a nice feature if the execution of tests doesn't get interrupted even in case of a fatal error. If the severe programming error doesn't harm other test cases, then it's ideal if the termination of a test case doesn't influence the life-time of other test cases.

Can panics be caught? At first sight, it may seem that User::SetExceptionHandler() would do. But it doesn't: exceptions are not the same as panics. So installing a new exception handler will not enable us to catch panics, even though it makes it possible to catch a small portion of ALL panics (e.g. an access violation aka KERN-EXE 3).

The ultimate solution is to let your test case run in a new thread. A new thread that you have control over: you create, destroy and most importantly monitor it. You can request notification when this thread dies normally or otherwise via RThread::Logon(). Combined this with RThread::ExitReason(), you can get a clue when and how a thread has exited. Even in case of a panic your main thread will not be affected at all so your - test - framework can continue to run.

The following example shows a console based exe which monitors other thread's death, displaying type and reason:

对,说的就是Panic。尽管就其本性来说,panic是“不可捕获的”,但仍有一种途径可以阻止它严重影响你的程序。

首先,为什么你要这样做呢?用况是什么?典型地,panic引起对应该已经在程序中更正的编程错误的注意。panic总是终止程序运行,并是故意这样设计的: 程序从“不可恢复的”运行阶段发生panic。因此,为什么我们需要捕获panic(假定我们能够这样做)?。

好了,至少有一个特殊的用处: 在测试框架中用于自动测试。在一个典型的单元测试框架中,比如,执行含有测试用例的测试集,若即使发生致命错误测试也不中断,这总是一个很好的功能。如果严重的编程错误不伤害其它的测试用例,那么某个测试用例的终止不影响其它用例的生命周期将是很理想的。

panic能被捕获吗?乍看起来,似乎User::SetExceptionHandler()能办到。但它却办不到。异常与panic不同。因此,安装一个新异常处理器不会使我们能捕获到panic,即使它使捕获一小部分异常成为可能(比如,访问违规或者说KERN-EXE 3)。

最终的解决方案: 让你的测试用例'运行在一个新线程中。一个你控制的新线程: 创建、销毁它,最重要的是监视它。经由RThread::Logon()你能够请求获知线程死亡正常与否。

下例演示了基于一个控制台的Exe,检测其他线程的死亡,显示类型及原因:

 

 view plaincopy to clipboardprint?
#ifndef THREADNOTIFIER_H  
#define THREADNOTIFIER_H  
   
#include <e32base.h>  
   
class CThreadNotifier : public CActive  
{  
public:  
    CThreadNotifier();  
    ~CThreadNotifier();  
    void ConstructL();  
   
    void IssueRequest();  
   
protected:  
    void RunL();  
    void DoCancel();  
    TInt RunError(TInt aError);  
   
    RUndertaker iUndertaker;  
    TInt iThreadHandle;  
};  
   
#endif 

 

 


#ifndef THREADNOTIFIER_H
#define THREADNOTIFIER_H
 
#include <e32base.h>
 
class CThreadNotifier : public CActive
{
public:
    CThreadNotifier();
    ~CThreadNotifier();
    void ConstructL();
 
    void IssueRequest();
 
protected:
    void RunL();
    void DoCancel();
    TInt RunError(TInt aError);
 
    RUndertaker iUndertaker;
    TInt iThreadHandle;
};
 
#endif

 

 

view plaincopy to clipboardprint?
#include "ThreadNotifier.h"  
   
#include <e32cons.h>  
   
_LIT(KPanicMsg, "THREAD-NOTIFIER");  
   
LOCAL_D CConsoleBase* console;  
   
CThreadNotifier::CThreadNotifier()  
    : CActive(CActive::EPriorityStandard)  
{  
    CActiveScheduler::Add(this);  
}  
   
void CThreadNotifier::ConstructL()  
{  
    User::LeaveIfError(iUndertaker.Create());  
}  
   
CThreadNotifier::~CThreadNotifier()  
{  
    Cancel();  
    iUndertaker.Close();  
}  
   
void CThreadNotifier::IssueRequest()  
{  
    __ASSERT_ALWAYS(!IsActive(), User::Panic(KPanicMsg, 0));  
   
    iUndertaker.Logon(iStatus, iThreadHandle);  
    SetActive();  
}  
   
void CThreadNotifier::RunL()  
{  
    if (iStatus == KErrDied)  
    {  
        RThread thread;  
        thread.SetHandle(iThreadHandle);  
        console->Printf(_L("Thread %S (%d) died (Type: %d, reason %d)/n"),   
&thread.Name(), (int)thread.Id(), thread.ExitType(), thread.ExitReason());  
        thread.Close();  
    }  
   
    IssueRequest();  
}  
   
void CThreadNotifier::DoCancel()  
{  
    iUndertaker.LogonCancel();  
}  
   
TInt CThreadNotifier::RunError(TInt /*aError*/)  
{  
    return KErrNone;  
}  
   
   
LOCAL_C void callExampleL()  
{  
    console = Console::NewL(_L("Thread Notifier"), TSize(KDefaultConsWidth,   
 KDefaultConsHeight));  
    CleanupStack::PushL(console);  
   
    CActiveScheduler* scheduler = new(ELeave) CActiveScheduler;  
    CleanupStack::PushL(scheduler);  
    CActiveScheduler::Install(scheduler);  
   
    CThreadNotifier* notifier = new(ELeave) CThreadNotifier;  
    CleanupStack::PushL(notifier);  
    notifier->ConstructL();  
    notifier->IssueRequest();  
   
    CActiveScheduler::Start();  
   
    CleanupStack::PopAndDestroy(3, console);    // console, scheduler, notifier  
}  
   
GLDEF_C TInt E32Main()  
{  
    __UHEAP_MARK;  
    CTrapCleanup* cleanup = CTrapCleanup::New();  
    TRAPD(error, callExampleL());  
    __ASSERT_ALWAYS(!error, User::Panic(KPanicMsg, error));  
    delete cleanup;  
    __UHEAP_MARKEND;  
    return 0;  
}

<think>好的,我需要帮助用户了解kernel.hung_task_panic参数的作用和配置方法。根据用户提供的引用内容,首先回顾一下已有的信息。 引用[1]提到,kernel.hung_task_panic的默认值是0,而引用[3]说明当这个参数设置为1时,系统会在检测到D状态进程超过指定时间后触发panic。接下来,我需要将这些信息整理成用户容易理解的步骤。 首先,参数的作用是控制是否在检测到hung task时让内核panic,这有助于通过kdump收集vmcore来调试问题。配置方法包括通过sysctl临时修改或者修改启动参数永久生效。需要检查用户提供的引用中是否有具体的配置示例,引用[1]中的sysctl命令显示了当前值,可以作为示例。 然后,需要注意的地方,比如生产环境谨慎启用panic,以及结合其他参数如timeout_secs调整检测阈值。用户可能需要知道如何验证配置是否生效,比如再次运行sysctl命令检查值是否正确。 最后,生成相关问题时要围绕参数的作用、配置步骤、注意事项和与其他参数的关系展开。确保问题覆盖用户可能感兴趣的方面,如性能影响、监控方法等。</think>### kernel.hung_task_panic 参数详解 #### 作用 `kernel.hung_task_panic` 是 Linux 内核中用于控制 **D状态进程(不可中断睡眠)检测机制** 的响应行为的参数: - **默认值**:0(仅打印警告日志,不触发系统崩溃)[^1] - **设置为1时**:当系统检测到进程处于 D 状态超过 `kernel.hung_task_timeout_secs`(默认120秒)时,会触发内核 panic,强制系统崩溃并生成 vmcore 文件(需配置kdump)[^3] #### 配置方法 **1. 临时配置(重启失效)** ```bash # 查看当前值 sysctl kernel.hung_task_panic # 修改参数 sysctl -w kernel.hung_task_panic=1 ``` **2. 永久配置(需重启)** ```bash # 编辑 sysctl.conf echo "kernel.hung_task_panic = 1" >> /etc/sysctl.conf # 或修改内核启动参数 在 GRUB_CMDLINE_LINUX 中添加 hung_task_panic=1 ``` **3. 验证配置** ```bash # 检查生效值 cat /proc/sys/kernel/hung_task_panic ``` #### 注意事项 1. **生产环境慎用**:触发 panic 会导致系统崩溃,仅建议调试环境使用 2. **依赖关系**:需配合 `kernel.hung_task_timeout_secs` 调整检测阈值[^1] 3. **日志监控**:通过 `dmesg | grep "hung_task"` 可查看相关警告 4. **内核线程**:khungtaskd 线程负责周期性检测(代码位置:`kernel/hung_task.c`)[^2] #### 典型应用场景 - 调试长时间 D 状态导致的系统冻结问题 - 与 kdump 配合捕捉内核故障现场 - 监控关键进程的异常阻塞情况
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值