Home > Erlang探索, 源码分析 > crash_dump中Taints项含义

crash_dump中Taints项含义

July 2nd, 2013

原创文章,转载请注明: 转载自系统技术非业余研究

本文链接地址: crash_dump中Taints项含义

erlang的应用程序出问题的时候通常会生成一个dump文件,这个文件很好的保存了当时的现场,很利于后面诊断问题。 比如:

=erl_crash_dump:0.1
Sun Jun 23 15:35:39 2013
Slogan: Kernel pid terminated (application_controller) ({application_start_failure,ump_proxy,{bad_return,{{ump_proxy_app,start,[normal,[]]},{‘EXIT’,{undef,[{cherly_server,start_link,[ump_proxy_cherly_server
System version: Erlang R15B02 (erts-5.9.2) [64-bit] [smp:16:16] [async-threads:5] [hipe] [kernel-poll:true]
Compiled: Fri Sep 14 13:23:22 2012
Taints: ump_proxy_partitioner_nifs,asn1rt_nif,crypto,dyntrace,ump_la_nifs
Atoms: 37857

crash_dump也开门见山的描述了出错的原因,系统的版本,编译时间,原子的个数,还有一个叫做Taints的东西。
前面这几个都很好理解,原子的个数也能理解,毕竟原子表是有大小限制的,爆了一定要crash的。 那这个Taints是哪路神仙,也要列在这么重要的位置。
从字面上理解,Taints的意思就是污染的意思,再看它的内容很明显都是nif模块的名字。
看到这些nif列表,大概就能明白了。由于nif是在vm里面运作的, 如果有bug或者问题,就会直接把vm挂掉,所以官方信任自己的vm代码,系统出了问题,第一时间就会怀疑到用户写的nif代码,也是很自然的。

Erlang开发组的人回答是:

The idea was a way to see all user libraries that has ever been loaded
and executed by the VM. Currently it only shows NIF libraries, but
driver names will hopefully be added as well in some future release.

/Sverker, Erlang/OTP Ericsson

我们从代码验证下:

/*break.c*/
void
erl_crash_dump_v(char *file, int line, char* fmt, va_list args)
{
...
    erts_fdprintf(fd, "System version: ");
    erts_print_system_version(fd, NULL, NULL);
    erts_fdprintf(fd, "%s\n", "Compiled: " ERLANG_COMPILE_DATE);
    erts_fdprintf(fd, "Taints: ");
    erts_print_nif_taints(fd, NULL);
...
}

/*erl_nif.c*/
void erts_print_nif_taints(int to, void* to_arg)
{
    struct tainted_module_t* t;
    const char* delim = "";
    for (t=first_tainted_module ; t!=NULL; t=t->next) {
        const Atom* atom = atom_tab(atom_val(t->module_atom));
        erts_print(to,to_arg,"%s%.*s", delim, atom->len, atom->name);
        delim = ",";
    }
    erts_print(to,to_arg,"\n");
}

static void add_taint(Eterm mod_atom)
{
    struct tainted_module_t* t;
    for (t=first_tainted_module ; t!=NULL; t=t->next) {
        if (t->module_atom == mod_atom) {
            return;
        }
    }
    t = erts_alloc_fnf(ERTS_ALC_T_TAINT, sizeof(*t));
    if (t != NULL) {
        t->module_atom = mod_atom;
        t->next = first_tainted_module;
        first_tainted_module = t;
    }
} 

BIF_RETTYPE load_nif_2(BIF_ALIST_2)
{
...  
 else if ((add_taint(mod_atom),
              (entry = erts_sys_ddll_call_nif_init(init_func)) == NULL)) {
        ret = load_nif_error(BIF_P, bad_lib, "Library init-call unsuccessful");
    } 
...
}

很清楚的看到每个nif加载的时候,都会被自动加入taints列表。
除了从crashdump看出taints列表, erlang还很贴心的提供了个函数:erlang:system_info(taints).
我们演示下这个功能:

$ erl
Erlang R15B03 (erts-5.9.3.1) [source] [64-bit] [smp:16:16] [async-threads:0] [hipe] [kernel-poll:false]

Eshell V5.9.3.1  (abort with ^G)
1> application:start(crypto).
ok
2> crypto:md5("test").
<<9,143,107,205,70,33,211,115,202,222,78,131,38,39,180,246>>
3> erlang:system_info(taints).
[crypto]
4> 

祝玩得开心!

Post Footer automatically generated by wp-posturl plugin for wordpress.

Comments are closed.