hung_task_timeout_secs 简单学习

简介:
[原文链接]

接上篇 简单学习了解下 hung_task_timeout_secs 相关知识.

OS: 2.6.18-194.32.1.el5 x86_64

# 先从系统中看下 hung_task 相关的参数及其参数值
[sina@localhost ~]$ sudo sysctl -a | grep hung
kernel.hung_task_warnings = 0
kernel.hung_task_timeout_secs = 120
kernel.hung_task_check_count = 4194304
kernel.hung_task_panic = 0
[sina@localhost ~]$


# 源码在此.... (v2.6.37.1)   & 结合看下kernel/sysctl.c更好
# kernel/hung_task.c
/*
 * Detect Hung Task
 *
 * kernel/hung_task.c - kernel thread for detecting tasks stuck in D state
 *
 */

#include <linux/mm.h>
#include <linux/cpu.h>
#include <linux/nmi.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/freezer.h>
#include <linux/kthread.h>
#include <linux/lockdep.h>
#include <linux/module.h>
#include <linux/sysctl.h>

/*
 * The number of tasks checked:
 */
unsigned long __read_mostly sysctl_hung_task_check_count = PID_MAX_LIMIT;

/*
 * Limit number of tasks checked in a batch.
 *
 * This value controls the preemptibility of khungtaskd since preemption
 * is disabled during the critical section. It also controls the size of
 * the RCU grace period. So it needs to be upper-bound.
 */
#define HUNG_TASK_BATCHING 1024

/*
 * Zero means infinite timeout - no checking done:
 */
unsigned long __read_mostly sysctl_hung_task_timeout_secs = 120;

unsigned long __read_mostly sysctl_hung_task_warnings = 10;

static int __read_mostly did_panic;

static struct task_struct *watchdog_task;

/*
 * Should we panic (and reboot, if panic_timeout= is set) when a
 * hung task is detected:
 */
unsigned int __read_mostly sysctl_hung_task_panic =
                CONFIG_BOOTPARAM_HUNG_TASK_PANIC_VALUE;

static int __init hung_task_panic_setup(char *str)
{
    sysctl_hung_task_panic = simple_strtoul(str, NULL, 0);

    return 1;
}
__setup("hung_task_panic=", hung_task_panic_setup);

static int
hung_task_panic(struct notifier_block *this, unsigned long event, void *ptr)
{
    did_panic = 1;

    return NOTIFY_DONE;
}

static struct notifier_block panic_block = {
    .notifier_call = hung_task_panic,
};

static void check_hung_task(struct task_struct *t, unsigned long timeout)
{
    unsigned long switch_count = t->nvcsw + t->nivcsw;

    /*
     * Ensure the task is not frozen.
     * Also, when a freshly created task is scheduled once, changes
     * its state to TASK_UNINTERRUPTIBLE without having ever been
     * switched out once, it musn't be checked.
     */
    if (unlikely(t->flags & PF_FROZEN || !switch_count))
        return;

    if (switch_count != t->last_switch_count) {
        t->last_switch_count = switch_count;
        return;
    }
    if (!sysctl_hung_task_warnings)
        return;
    sysctl_hung_task_warnings--;

    /*
     * Ok, the task did not get scheduled for more than 2 minutes,
     * complain:
     */
    printk(KERN_ERR "INFO: task %s:%d blocked for more than "
            "%ld seconds.\n", t->comm, t->pid, timeout);
    printk(KERN_ERR "\"echo 0 > /proc/sys/kernel/hung_task_timeout_secs\""
            " disables this message.\n");
    sched_show_task(t);
    debug_show_held_locks(t);

    touch_nmi_watchdog();

    if (sysctl_hung_task_panic)
        panic("hung_task: blocked tasks");
}

/*
 * To avoid extending the RCU grace period for an unbounded amount of time,
 * periodically exit the critical section and enter a new one.
 *
 * For preemptible RCU it is sufficient to call rcu_read_unlock in order
 * to exit the grace period. For classic RCU, a reschedule is required.
 */
static void rcu_lock_break(struct task_struct *g, struct task_struct *t)
{
    get_task_struct(g);
    get_task_struct(t);
    rcu_read_unlock();
    cond_resched();
    rcu_read_lock();
    put_task_struct(t);
    put_task_struct(g);
}

/*
 * Check whether a TASK_UNINTERRUPTIBLE does not get woken up for
 * a really long time (120 seconds). If that happens, print out
 * a warning.
 */
static void check_hung_uninterruptible_tasks(unsigned long timeout)
{
    int max_count = sysctl_hung_task_check_count;
    int batch_count = HUNG_TASK_BATCHING;
    struct task_struct *g, *t;

    /*
     * If the system crashed already then all bets are off,
     * do not report extra hung tasks:
     */
    if (test_taint(TAINT_DIE) || did_panic)
        return;

    rcu_read_lock();
    do_each_thread(g, t) {
        if (!max_count--)
            goto unlock;
        if (!--batch_count) {
            batch_count = HUNG_TASK_BATCHING;
            rcu_lock_break(g, t);
            /* Exit if t or g was unhashed during refresh. */
            if (t->state == TASK_DEAD || g->state == TASK_DEAD)
                goto unlock;
        }
        /* use "==" to skip the TASK_KILLABLE tasks waiting on NFS */
        if (t->state == TASK_UNINTERRUPTIBLE)
            check_hung_task(t, timeout);
    } while_each_thread(g, t);
 unlock:
    rcu_read_unlock();
}

static unsigned long timeout_jiffies(unsigned long timeout)
{
    /* timeout of 0 will disable the watchdog */
    return timeout ? timeout * HZ : MAX_SCHEDULE_TIMEOUT;
}

/*
 * Process updating of timeout sysctl
 */
int proc_dohung_task_timeout_secs(struct ctl_table *table, int write,
                  void __user *buffer,
                  size_t *lenp, loff_t *ppos)
{
    int ret;

    ret = proc_doulongvec_minmax(table, write, buffer, lenp, ppos);

    if (ret || !write)
        goto out;

    wake_up_process(watchdog_task);

 out:
    return ret;
}

/*
 * kthread which checks for tasks stuck in D state
 */
static int watchdog(void *dummy)
{
    set_user_nice(current, 0);

    for ( ; ; ) {
        unsigned long timeout = sysctl_hung_task_timeout_secs;

        while (schedule_timeout_interruptible(timeout_jiffies(timeout)))
            timeout = sysctl_hung_task_timeout_secs;

        check_hung_uninterruptible_tasks(timeout);
    }

    return 0;
}

static int __init hung_task_init(void)
{
    atomic_notifier_chain_register(&panic_notifier_list, &panic_block);
    watchdog_task = kthread_run(watchdog, NULL, "khungtaskd");

    return 0;
}

module_init(hung_task_init);
 
 
 
[ -EOF- ]
相关文章
|
SQL 关系型数据库 MySQL
Lock wait timeout exceeded; try restarting transaction解决方案
在测试程序时,打的断点怎么都跳不进去,console一直报 “Lock wait timeout exceeded; try restarting transaction”
438 0
|
存储 Java
A timeout exceeded while waiting to proceed with the request, please reduce your request rate【已解决】
A timeout exceeded while waiting to proceed with the request, please reduce your request rate【已解决】
642 0
|
网络协议 测试技术
TIME_WAIT过多及解决
最近用http_load做压测,跑出来一大串“Cannot assign requested address ”的错误,查了一下,是TIME_WAIT过多导致的。因为短时间内有太多连接,所以占用了大量端口,同时关闭连接后又处于TIME_WAIT状态,端口不能复用,所以慢慢的无端口可用,所以就“Cannot assign requested address”了。
1116 1
|
关系型数据库 MySQL 数据库
interactive_timeout和wait_timeout的关系
interactive_timeout = 28800 wait_timeout = 28800 #这两个参数默认都是28800s,即8个小时; interactive_timeout指的是mysql在关闭一个交互的连接之前所要等待的秒数 wait_timeout指的是mysql在关闭一个非交互的连接之前所要等待的秒数 通过mysql客户端连接数据库是交互式连接,通过jdbc连接数据库是非交互式连接 (1)session级别修改interactive_timeout=10,wait_timeout默认不变。
2266 0
|
MySQL 关系型数据库 Perl
timed out waiting for to be synced
程序操作kubernetes资源时, 没有等旧的资源删除完毕就立即创建了同名的新资源, 导致出现了一些错误.  具体表现为kubernetes命令行删除StatefulSet时报错, timed out waiting for "mysql" to be synced, 删除多次卡住, 然后报这个超时错误.
3080 0
|
NoSQL Redis Sentinel