首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > 编程 >

erlang虚拟机topology不符招致启动后crash

2013-12-26 
erlang虚拟机topology不符导致启动后crash线上有一台t4的机器,这些机器的cpu topo是经过伪造的,通过top命

erlang虚拟机topology不符导致启动后crash

线上有一台t4的机器,这些机器的cpu topo是经过伪造的,通过top命令可以看到4个核心:

top

Cpu0 ?: ?0.3%us, ?0.0%sy, ?0.0%ni, 99.0%id, ?0.0%wa, ?0.0%hi, ?0.0%si, ?0.7%st

Cpu1 ?: ?0.7%us, ?0.3%sy, ?0.0%ni, 98.7%id, ?0.0%wa, ?0.0%hi, ?0.0%si, ?0.3%st

Cpu2 ?: ?0.3%us, ?0.7%sy, ?0.0%ni, 78.1%id, ?0.0%wa, ?0.0%hi, ?0.0%si, 20.9%st

Cpu3 ?: ?0.0%us, ?0.3%sy, ?0.0%ni, 79.2%id, ?0.0%wa, ?0.0%hi, ?0.0%si, 20.5%st

/proc/cpu_info下也是4个核心:

cat /proc/cpuinfo?

processor ? ? ? : 0

physical id ? ? : 0

core id ? ? ? ? : 0

cpu cores ? ? ? : 4

?

processor ? ? ? : 1

physical id ? ? : 0

core id ? ? ? ? : 1

cpu cores ? ? ? : 4

?

processor ? ? ? : 2

physical id ? ? : 0

core id ? ? ? ? : 2

cpu cores ? ? ? : 4

?

processor ? ? ? : 3

physical id ? ? : 0

core id ? ? ? ? : 3

cpu cores ? ? ? : 4

?

但实际机器有24个核心:

cat /sys/devices/system/cpu/online?

0-23

在这台机器上编译erlang虚拟机或安装已经打包的虚拟机,全部会报出segment falut的错误,对于这个问题,进行了跟踪。

首先可以确认,erlang虚拟机本身是可以正确编译好的,这给我们提供了gdb跟踪的条件,跟踪发现:

main

|-erts_cpu_info_create

? |-erts_cpu_info_update

? ? |-configured = (int) sysconf(_SC_NPROCESSORS_CONF);

? ? | 使用sysconf得到cpu个数,此处得到的是伪造的4

? ? |-cpuinfo->configured = configured;

? ? |-read_topology

? ? ? |-cpuinfo->topology = malloc(sizeof(erts_cpu_topology_t) * cpuinfo->configured);

? ? ? | 此处为拓扑信息分配空间,数量为从sysconf处获得的cpu个数

? ? ? |-cdir = opendir("/sys/devices/system/cpu");

? ? ? |-do {

? ? ? ? ? struct dirent *cde = readdir(cdir);

? ? ? ? ? if (sscanf(cde->d_name, "cpu%d", &cpu_id) == 1) {

? ? ? ? ? ? sprintf(fpath, "%s/cpu%d/topology/physical_package_id", cpath, cpu_id);

? ? ? ? ? ? if (read_file(fpath, buf, sizeof(buf)) <= 0) continue;

? ? ? ? ? ? 读取/sys/devices/system/cpu/cpu#/topology/physical_package_id,注意这将取出配置的4个cpu之外的cpu的物理封包id

? ? ? ? ? ? sprintf(fpath, "%s/cpu%d/topology/physical_package_id", cpath, cpu_id);

? ? ? ? ? ? if (read_file(fpath, buf, sizeof(buf)) <= 0) continue;

? ? ? ? ? ? 读取/sys/devices/system/cpu/cpu#/topology/core_id,注意这将取出配置的4个cpu之外的cpu的核心id

? ? ? ? ? ? ix++;

? ? ? ? ? ? cpuinfo->topology[ix].node= node_id;

? ? ? ? ? ? 在ix超过4时,该处动作将越界访问cpuinfo->topology分配的内存,引发segment fault

? ? ? ? ? }

? ? ? ? } while (got_nodes);

自此,已经得到了问题的原因,t4机器伪造的cpu拓扑信息并不完全,erlang虚拟机在启动的时候会额外检查/sys/devices/system/cpu下

具体的cpu信息,这些信息与通过sysconf得到的信息不符,进而引发了越界的访存。

这个问题的fix方案有几种,举例如下:

1.修改erlang代码,将configured赋予一个足够大的值,避免访存越界,然后通过启动时加入参数或设置环境变量sct强制控制cpu拓扑,

? 如:export ERL_FLAGS="+sct L0-3c0-3";

2.修改erlang代码,在循环读取真实拓扑信息时,忽略超过configured数量的cpu的信息,同样,启动时加入参数或设置环境变量sct;

3.令额外的cpu信息对erlang虚拟机不可见。

这个坑比较容易误导,今后应避免。

?

热点排行