⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 break.c

📁 OTP是开放电信平台的简称
💻 C
📖 第 1 页 / 共 2 页
字号:
/* ``The contents of this file are subject to the Erlang Public License, * Version 1.1, (the "License"); you may not use this file except in * compliance with the License. You should have received a copy of the * Erlang Public License along with this software. If not, it can be * retrieved via the world wide web at http://www.erlang.org/. *  * Software distributed under the License is distributed on an "AS IS" * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See * the License for the specific language governing rights and limitations * under the License. *  * The Initial Developer of the Original Code is Ericsson Utvecklings AB. * Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings * AB. All Rights Reserved.'' *  *     $Id$ *//* This File contains functions which are called if a user hits ^C */#ifdef HAVE_CONFIG_H#  include "config.h"#endif#include "sys.h"#include "erl_vm.h"#include "global.h"#include "erl_process.h"#include "version.h"#include "error.h"#include "version.h"#include "erl_db.h"#include "bif.h"#include "erl_version.h"#include "hash.h"#include "atom.h"#include "beam_load.h"#include "erl_instrument.h"#include "erl_bif_timer.h"#ifdef _OSE_#include "time.h"#endif/* Forward declarations -- should really appear somewhere else */static void process_killer(void);void do_break(void);void erl_crash_dump_v(char *file, int line, char* fmt, va_list args);void erl_crash_dump(char* file, int line, char* fmt, ...);#ifdef DEBUGstatic void bin_check(void);#endifstatic void print_garb_info(int to, void *to_arg, Process* p);#ifdef OPPROFstatic void dump_frequencies(void);#endifstatic void dump_attributes(int to, void *to_arg, byte* ptr, int size);extern char* erts_system_version[];static voidport_info(int to, void *to_arg){    int i;    for (i = 0; i < erts_max_ports; i++)	print_port_info(to, to_arg, i);}voidprocess_info(int to, void *to_arg){    int i;    for (i = 0; i < erts_max_processes; i++) {	if ((process_tab[i] != NULL) && (process_tab[i]->i != ENULL)) {	   if (process_tab[i]->status != P_EXITING)	       print_process_info(to, to_arg, process_tab[i]);	}    }    port_info(to, to_arg);}static voidprocess_killer(void){    int i, j;    Process* rp;    erts_printf("\n\nProcess Information\n\n");    erts_printf("--------------------------------------------------\n");    for (i = erts_max_processes-1; i >= 0; i--) {	if (((rp = process_tab[i]) != NULL) && rp->i != ENULL) {	    int br;	    print_process_info(ERTS_PRINT_STDOUT, NULL, rp);	    erts_printf("(k)ill (n)ext (r)eturn:\n");	    while(1) {		if ((j = sys_get_key(0)) <= 0)		    halt_0(0);		switch(j) {		case 'k':		    if (rp->status == P_WAITING) {			Uint32 rp_locks = ERTS_PROC_LOCKS_XSIG_SEND;			erts_smp_proc_lock(rp, rp_locks);			(void) erts_send_exit_signal(NULL,						     NIL,						     rp,						     &rp_locks,						     am_kill,						     NIL,						     NULL,						     0);			erts_smp_proc_unlock(rp, rp_locks);		    }		    else			erts_printf("Can only kill WAITING processes this way\n");		case 'n': br = 1; break;		case 'r': return;		default: return;		}		if (br == 1) break;	    }	}    }}typedef struct {    int is_first;    int to;    void *to_arg;} PrintMonitorContext;static void doit_print_link(ErtsLink *lnk, void *vpcontext){    PrintMonitorContext *pcontext = vpcontext;    int to = pcontext->to;    void *to_arg = pcontext->to_arg;    if (pcontext->is_first) {	pcontext->is_first = 0;	erts_print(to, to_arg, "%T", lnk->pid);    } else {	erts_print(to, to_arg, ", %T", lnk->pid);    }}    static void doit_print_monitor(ErtsMonitor *mon, void *vpcontext){    PrintMonitorContext *pcontext = vpcontext;    int to = pcontext->to;    void *to_arg = pcontext->to_arg;    char *prefix = ", ";     if (pcontext->is_first) {	pcontext->is_first = 0;	prefix = "";    }    if (mon->type == MON_ORIGIN) {	if (is_atom(mon->pid)) { /* dist by name */	    ASSERT(is_node_name_atom(mon->pid));	    erts_print(to, to_arg, "%s{to,{%T,%T},%T}", prefix, mon->name,		       mon->pid, mon->ref);	    erts_print(to, to_arg,"}");	} else if (is_atom(mon->name)){ /* local by name */	    erts_print(to, to_arg, "%s{to,{%T,%T},%T}", prefix, mon->name,		       erts_this_dist_entry->sysname, mon->ref);	} else { /* local and distributed by pid */	    erts_print(to, to_arg, "%s{to,%T,%T}", prefix, mon->pid, mon->ref);	}    } else { /* MON_TARGET */	erts_print(to, to_arg, "%s{from,%T,%T}", prefix, mon->pid, mon->ref);    }}			       /* Display info about an individual Erlang process */voidprint_process_info(int to, void *to_arg, Process *p){    int garbing = 0;    int running = 0;    /* display the PID */    erts_print(to, to_arg, "=proc:%T\n", p->id);    /* Display the state */    erts_print(to, to_arg, "State: ");    switch (p->status) {    case P_FREE:	erts_print(to, to_arg, "Non Existing\n"); /* Should never happen */	break;    case P_RUNABLE:	erts_print(to, to_arg, "Scheduled\n");	break;    case P_WAITING:	erts_print(to, to_arg, "Waiting\n");	break;    case P_SUSPENDED:	erts_print(to, to_arg, "Suspended\n");	break;    case P_RUNNING:	erts_print(to, to_arg, "Running\n");	running = 1;	break;    case P_EXITING:	erts_print(to, to_arg, "Exiting\n");	break;    case P_GARBING:	erts_print(to, to_arg, "Garbing\n");	garbing = 1;	running = 1;	break;    }    /*     * If the process is registered as a global process, display the     * registered name     */    if (p->reg != NULL)	erts_print(to, to_arg, "Name: %T\n", p->reg->name);    /*     * Display the initial function name     */    erts_print(to, to_arg, "Spawned as: %T:%T/%bpu\n",	       p->initial[INITIAL_MOD],	       p->initial[INITIAL_FUN],	       p->initial[INITIAL_ARI]);        if (p->current != NULL) {	if (running) {	    erts_print(to, to_arg, "Last scheduled in for: ");	} else {	    erts_print(to, to_arg, "Current call: ");	}	erts_print(to, to_arg, "%T:%T/%bpu\n",		   p->current[0],		   p->current[1],		   p->current[2]);    }    erts_print(to, to_arg, "Spawned by: %T\n", p->parent);    erts_print(to, to_arg, "Started: %s", ctime((time_t*)&p->started));    ERTS_SMP_MSGQ_MV_INQ2PRIVQ(p);    erts_print(to, to_arg, "Message queue length: %d\n", p->msg.len);    /* display the message queue only if there is anything in it */    if (!ERTS_IS_CRASH_DUMPING && p->msg.first != NULL && !garbing) {	ErlMessage* mp;	erts_print(to, to_arg, "Message queue: [");	for (mp = p->msg.first; mp; mp = mp->next)	    erts_print(to, to_arg, mp->next ? "%T," : "%T", ERL_MESSAGE_TERM(mp));	erts_print(to, to_arg, "]\n");    }    {       long s = 0;       int frags = 0;       ErlHeapFragment *m = p->mbuf;       while (m != NULL) {	   frags++;	   s += m->size;	   m = m->next;       }       erts_print(to, to_arg, "Number of heap fragments: %d\n", frags);    }    erts_print(to, to_arg, "Heap fragment data: %bpu\n", MBUF_SIZE(p));    if (p->ct != NULL) {       int i, j;       erts_print(to, to_arg, "Last calls:");       for (i = 0; i < p->ct->n; i++) {	     erts_print(to, to_arg, " ");	     j = p->ct->cur - i - 1;	     if (j < 0)		j += p->ct->len;	     if (p->ct->ct[j] == &exp_send)		erts_print(to, to_arg, "send");	     else if (p->ct->ct[j] == &exp_receive)		erts_print(to, to_arg, "'receive'");	     else if (p->ct->ct[j] == &exp_timeout)		   erts_print(to, to_arg, "timeout");	     else		 erts_print(to, to_arg, "%T:%T/%bpu\n",			    p->ct->ct[j]->code[0],			    p->ct->ct[j]->code[1],			    p->ct->ct[j]->code[2]);       }       erts_print(to, to_arg, "\n");    }    /* display the links only if there are any*/    if (p->nlinks != NULL || p->monitors != NULL) {	PrintMonitorContext context = {1,to}; 	erts_print(to, to_arg,"Link list: [");	erts_doforall_links(p->nlinks, &doit_print_link, &context);		erts_doforall_monitors(p->monitors, &doit_print_monitor, &context);	erts_print(to, to_arg,"]\n");    }    if (!ERTS_IS_CRASH_DUMPING) {	/* and the dictionary */	if (p->dictionary != NULL && !garbing) {	    erts_print(to, to_arg, "Dictionary: ");	    erts_dictionary_dump(to, to_arg, p->dictionary);	    erts_print(to, to_arg, "\n");	}    	/* as well as the debug dictionary */	if (p->debug_dictionary != NULL && !garbing) {	    erts_print(to, to_arg, "$Dictionary: ");	    erts_dictionary_dump(to, to_arg, p->debug_dictionary);	    erts_print(to, to_arg, "\n");	}    }        /* print the number of reductions etc */    erts_print(to, to_arg, "Reductions: %bpu\n", p->reds);    erts_print(to, to_arg, "Stack+heap: %bpu\n", p->heap_sz);    erts_print(to, to_arg, "OldHeap: %bpu\n",               (OLD_HEAP(p) == NULL) ? 0 :               (unsigned)(OLD_HEND(p) - OLD_HEAP(p)) );    erts_print(to, to_arg, "Heap unused: %bpu\n", (p->hend - p->htop));    erts_print(to, to_arg, "OldHeap unused: %bpu\n",	       (OLD_HEAP(p) == NULL) ? 0 : (OLD_HEND(p) - OLD_HEAP(p)) );    if (garbing) {	print_garb_info(to, to_arg, p);    }        if (ERTS_IS_CRASH_DUMPING) {	erts_program_counter_info(to, to_arg, p);    } else {	erts_print(to, to_arg, "Stack dump:\n");#ifdef ERTS_SMP	if (!garbing)#endif	    erts_stack_dump(to, to_arg, p);    }}static voidprint_garb_info(int to, void *to_arg, Process* p){    /* ERTS_SMP: A scheduler is probably concurrently doing gc... */#ifndef ERTS_SMP    erts_print(to, to_arg, "New heap start: %bpX\n", p->heap);    erts_print(to, to_arg, "New heap top: %bpX\n", p->htop);    erts_print(to, to_arg, "Stack top: %bpX\n", p->stop);    erts_print(to, to_arg, "Stack end: %bpX\n", p->hend);    erts_print(to, to_arg, "Old heap start: %bpX\n", OLD_HEAP(p));    erts_print(to, to_arg, "Old heap top: %bpX\n", OLD_HTOP(p));    erts_print(to, to_arg, "Old heap end: %bpX\n", OLD_HEND(p));#endif}voidinfo(int to, void *to_arg){    erts_memory(&to, to_arg, NULL, THE_NON_VALUE);    atom_info(to, to_arg);    module_info(to, to_arg);    export_info(to, to_arg);    register_info(to, to_arg);    erts_fun_info(to, to_arg);    erts_node_table_info(to, to_arg);    erts_dist_table_info(to, to_arg);    erts_allocated_areas(&to, to_arg, NULL);    erts_allocator_info(to, to_arg);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -