FT2000+ qemu kvm 红旗 crash 分析 频繁设置CPU online及cgroup导致进程卡死、不调度故障

news/2024/7/21 8:56:29 标签: virsh, kvm, kernel

测试程序

/**
tcti.cpp

参考:
https://www.cnblogs.com/organic/p/17321523.html

g++ -std=c++11 -lpthread trigger_cgroup_timer_inactive.cpp -o inactive_timer
./inactive_timer 100000 10000
*/

#include <errno.h>
#include <iostream>
#include <pthread.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <string>
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>

#ifndef CPU_CORE_COUNT
#define CPU_CORE_COUNT 64
#endif

using namespace std;
std::string sub_cgroup_dir("/sys/fs/cgroup/cpu/test");

// common lib
bool is_dir(const std::string &path) {
  struct stat statbuf;
  if (stat(path.c_str(), &statbuf) == 0) {
    if (0 != S_ISDIR(statbuf.st_mode)) {
      return true;
    }
  }
  return false;
}

bool write_file(const std::string &file_path, int num) {
  // std::cout << file_path << " op:" << num << std::endl;
  FILE *fp = fopen(file_path.c_str(), "w");
  if (fp == NULL) {
    return false;
  }

  // std::cout << file_path << " op:" << num << std::endl;
  std::string write_data = to_string(num);
  fputs(write_data.c_str(), fp);
  fclose(fp);
  return true;
}

std::string read_file(const std::string &file_path) {
  FILE *fp = fopen(file_path.c_str(), "r");
  if (NULL == fp) {
    return "read error...\n";
  }
  char buff[512];
  memset(buff, 0, 512);
  fread(buff, 512, 1, fp);
  fclose(fp);
  return std::string(buff);
}

// ms
long get_ms_timestamp() {
  timeval tv;
  gettimeofday(&tv, NULL);
  return (tv.tv_sec * 1000 + tv.tv_usec / 1000);
}

// cgroup
bool create_cgroup() {
  if (is_dir(sub_cgroup_dir) == false) {
    if (mkdir(sub_cgroup_dir.c_str(), S_IRWXU | S_IRGRP) != 0) {
      cout << "mkdir cgroup dir fail" << endl;
      return false;
    }
  }

  int pid = getpid();
  cout << "pid is " << pid << endl;
  std::string procs_path = sub_cgroup_dir + "/cgroup.procs";
  return write_file(procs_path, pid);
}

bool set_period(int period) {
  std::string period_path = sub_cgroup_dir + "/cpu.cfs_period_us";
  return write_file(period_path, period);
}

bool set_quota(int quota) {
  std::string quota_path = sub_cgroup_dir + "/cpu.cfs_quota_us";
  return write_file(quota_path, quota);
}

bool set_cpuOnline(int cpuId, int online) {
  std::string cpuPath = std::string("/sys/devices/system/cpu/cpu") +
                        std::to_string(cpuId) + std::string("/online");
  return write_file(cpuPath, online);
}

// thread
// param: ms interval
void *thread_func(void *param) {
  int i = 0;
  int interval = (long)param;
  long last = get_ms_timestamp();

  while (true) {
    i++;
    if (i % 100000 != 0) {
      continue;
    }

    long current = get_ms_timestamp();
    if ((current - last) >= interval) {
      last = current;
    }
  }

  pthread_exit(NULL);
}

void test_thread() {
  const int k_thread_num = CPU_CORE_COUNT * 10;
  pthread_t pthreads[k_thread_num];

  for (int i = 0; i < k_thread_num; i++) {
    if (pthread_create(&pthreads[i], NULL, thread_func, (void *)(i + 1)) != 0) {
      cout << "create thread fail" << endl;
    } else {
      cout << "create thread success,tid is " << pthreads[i] << endl;
    }
  }
}

void *thread_cpu_online_ctl(void *param) {
  int online, cpu;
  bool b;
  while (true) {
    online = rand() % 2;
    cpu = rand() % CPU_CORE_COUNT;
    b = set_cpuOnline(cpu, online);
    std::cout << cpu << " -> " << online << "result:" << b << std::endl;
    std::cout << read_file("/sys/devices/system/cpu/online") << std::endl;
  }

  pthread_exit(NULL);
}

void cpu_ctl_thread() {
  const int k_thread_num = CPU_CORE_COUNT;
  pthread_t pthreads[k_thread_num];

  for (int i = 0; i < k_thread_num; i++) {
    if (pthread_create(&pthreads[i], NULL, thread_cpu_online_ctl,
                       (void *)(i + 1)) != 0) {
      cout << "create thread fail" << endl;
    } else {
      cout << "create thread success,tid is " << pthreads[i] << endl;
    }
  }
}

int main(int argc, char *argv[]) {

  int period = 100000;
  int quota = CPU_CORE_COUNT * 0.8 * 100000;
  cout << "period is " << period << endl;
  cout << "quota is " << quota << endl;
  srand(time(nullptr));

  test_thread();
  cpu_ctl_thread();
  if (create_cgroup() == false) {
    cout << "create cgroup fail" << endl;
    return -1;
  }

  set_period(period);
  set_quota(quota);

  while (true) {
    sleep(10000);
  }

  return 0;
}

故障现象

64C64G运行一个多小时后,进程不再输出,无法停止(如果此时重启,系统会卡在重启过程)

crash 分析

virsh dump

 virsh reset

 vnc登录,crash

 分析

ps | grep tcti |less

 所有测试程序均标记为运行状态。实际上并没有CPU使用了了。

set pid ; runq -c cpuid

 查看pid=2743进程状态为运行中,CPU号=2

runq查看CPU号=2的运行队列,显示no tasks queued

即:进程被标记在CPU2上正在运行,而CPU2上显示没有任何任务队列。

查看task对应的se没有在rq上,cfs_rq显示被throttled

 runq -c 2 -g

 由于CONFIG_RT_GROUP_SCHED未配置,因此无法查看task_group.rt_bandwith

 参考以下文章

https://www.cnblogs.com/organic/p/17321523.html

根据其分析,当故障发生时,手动设置下cgroup限制即可触发定时器恢复调用

复测验证

复现进程假死

 所有线程CPU均无使用率(ssh远程登录上去)

 手动修改下cgroup配置

 发现指令被卡主

说明本文的现象与

https://www.cnblogs.com/organic/p/17321523.html

所描述有差异。(同时也不可继续操作cpu online状态)

本文中测试程序添加了cpu online状态设置,原目的是尝试触发_nohz_idle_balance,分析以前发生的类似故障。

目前已知情况

OS内核故障
CentOS8.3.20114.18.0-240.el8.aarch64容易复现
RedFlag74.19.133-300.axs7.14.aarch64容易复现
openEuler 20.03 LTS SP34.19.90-2112.8.0.0131.oe1.aarch64可复现
openEuler 22.03 LTS5.10.0-60.18.0.50.oe2203.aarch64未复现

从上述表格可以推测,该调度问题,在openEuler 22.03 LTS版本内核已经修复过。


http://www.niftyadmin.cn/n/298998.html

相关文章

第三十章 React的路由基本使用

关于React路由&#xff0c;我们在学习之前先了解一下其他知识点&#xff1a;SPA应用、路由的理解、react中如何使用路由。 SPA应用的理解 我们知道React脚手架给我们构建的是一个单页应用程序&#xff08;SPA&#xff09;&#xff0c;在页面加载时&#xff0c;只会加载一个HT…

JVM系列-第5章-堆(JVisualVM)

堆 堆的核心概述 堆与进程 堆针对一个JVM进程来说是唯一的。也就是一个进程只有一个JVM实例&#xff0c;一个JVM实例中就有一个运行时数据区&#xff0c;一个运行时数据区只有一个堆和一个方法区。 但是进程包含多个线程&#xff0c;他们是共享同一堆空间的。 一个JVM实例…

美颜sdk的开发流程及其在不同平台上的适用性比较

当下&#xff0c;在开发美颜功能时&#xff0c;美颜sdk成为了不可或缺的工具。近期&#xff0c;很多开发者向小编提问开发美颜的一些专业技术问题。本篇文章&#xff0c;小编将为大家统一解答一下近期的热门问题。 一、开发流程 1、确定美颜算法 美颜算法是美颜sdk的核心&a…

时至今日,Pascal系列Turbo Pascal 5.0依旧是我心中永远的神

从DOS时代到Windows时代&#xff0c;从桌面应用到Web应用&#xff0c;每一个时代都有它特定的编程工具 在我看来&#xff0c;DOS时代的编程语言&#xff0c;Pascal必占一席之地。 尤其是Turbo Pascal系列的最后一个版本——Turbo Pascal 5.0&#xff0c;更是我心目中永不褪色的…

vscode IDE 能用的上的扩展工具功能介绍

记录分享vscode扩展&#xff0c;包括提升开发效率。必备。主题美化。ChatGPT等。 参考 vscode-extensions [Best] 记录分享方式&#xff0c;整理自己用的扩展&#xff0c;还有一键备份和还原方法。 ⭐快速下载和使用扩展 后面会介绍很多vscode扩展.这裡有一个技巧&#xff0c;…

【Nacos源码分析】

Nacos源码分析 Nacos源码分析1.下载Nacos源码并运行1.1.下载Nacos源码1.2.导入Demo工程1.3.导入Nacos源码1.4.proto编译1.4.1.什么是protobuf1.4.2.安装protoc1.4.3.编译proto 1.5.运行 2.服务注册2.1.服务注册接口2.2.客户端2.2.1.NacosServiceRegistryAutoConfiguration2.2.2…

从Facebook到Diem币:社交媒体巨头在加密货币领域的演变

大家都知道Facebook是一个全球知名的社交媒体平台&#xff0c;几乎每个人都在其中与朋友分享照片、发表状态或留言。 然而&#xff0c;随着时间的推移&#xff0c;Facebook不仅仅局限于社交交流&#xff0c;而是逐渐涉足更广阔的领域&#xff0c;其中之一就是加密货币。在本文…

SHOP.COM EDI需求分析

Market America | SHOP.COM 是一家全球电子商务和数字营销公司&#xff0c;成立于1992年&#xff0c;总部位于北卡罗来纳州格林斯伯勒。该公司为企业家提供了一个补充收入的系统&#xff0c;同时为消费者提供了更好的购物平台。平台上有众多品牌和商家提供商品&#xff0c;用户…