1. 程式人生 > >系統技術非業餘研究 » crash_dump中Taints項含義

系統技術非業餘研究 » 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)  [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.