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

📄 erl_trace.c

📁 OTP是开放电信平台的简称
💻 C
📖 第 1 页 / 共 5 页
字号:
	ASSERT(is_internal_pid(p->tracer_proc)	       && internal_pid_index(p->tracer_proc) < erts_max_processes);#ifndef ERTS_SMP	tracer = process_tab[internal_pid_index(p->tracer_proc)];	if (INVALID_PID(tracer, p->tracer_proc)	    || (tracer->trace_flags & F_TRACER) == 0) {	    p->trace_flags &= ~TRACEE_FLAGS;	    p->tracer_proc = NIL;	    return;	}#endif	size = size_object(mess);#ifdef ERTS_SMP	bp = new_message_buffer(size);	hp = bp->mem;	off_heap = &bp->off_heap;#else	hp = erts_alloc_message_heap(size, &bp, &off_heap, tracer, 0);#endif		/*	 * Copy the trace message into the buffer and enqueue it.	 */	mess = copy_struct(mess, size, &hp, off_heap);#ifdef ERTS_SMP	enqueue_sys_msg_unlocked(SYS_MSG_TYPE_TRACE,				 p->id, p->tracer_proc, mess, bp);#else	erts_queue_message(tracer, 0, bp, mess, NIL);#endif    }    erts_smp_mtx_unlock(&smq_mtx);}/* Send {trace_ts, Pid, return_from, {Mod, Name, Arity}, Retval, Timestamp} * or   {trace, Pid, return_from, {Mod, Name, Arity}, Retval} */voiderts_trace_return(Process* p, Eterm* fi, Eterm retval, Eterm *tracer_pid){    Eterm* hp;    Eterm mfa;    Eterm mess;    Eterm mod, name;    int arity;    Uint meta_flags, *tracee_flags;#ifdef ERTS_SMP    Eterm tracee;#endif        ASSERT(tracer_pid);    if (*tracer_pid == am_true) {	/* Breakpoint trace enabled without specifying tracer =>	 *   use process tracer and flags	 */	tracer_pid = &p->tracer_proc;    }    if (is_nil(*tracer_pid)) {	/* Trace disabled */	return;    }    ASSERT(is_internal_pid(*tracer_pid) || is_internal_port(*tracer_pid));    if (*tracer_pid == p->id) {	/* Do not generate trace messages to oneself */	return;    }    if (tracer_pid == &p->tracer_proc) {	/* Tracer specified in process structure =>	 *   non-breakpoint trace =>	 *     use process flags	 */	tracee_flags = &p->trace_flags;#ifdef ERTS_SMP	tracee = p->id;#endif    } else {	/* Tracer not specified in process structure =>	 *   tracer specified in breakpoint =>	 *     meta trace =>	 *       use fixed flag set instead of process flags	 */	    	meta_flags = F_TRACE_CALLS | F_TIMESTAMP;	tracee_flags = &meta_flags;#ifdef ERTS_SMP	tracee = NIL;#endif    }    if (! (*tracee_flags & F_TRACE_CALLS)) {	return;    }        mod = fi[0];    name = fi[1];    arity = fi[2];        if (is_internal_port(*tracer_pid)) {	Eterm local_heap[4+6+5];	hp = local_heap;	mfa = TUPLE3(hp, mod, name, make_small(arity));	hp += 4;	mess = TUPLE5(hp, am_trace, p->id, am_return_from, mfa, retval);	hp += 6;	erts_smp_mtx_lock(&smq_mtx);	if (*tracee_flags & F_TIMESTAMP) {	    hp = patch_ts(mess, hp);	}	send_to_port(p, mess, tracer_pid, tracee_flags);	erts_smp_mtx_unlock(&smq_mtx);    } else {	ErlHeapFragment *bp;	ErlOffHeap *off_heap;#ifndef ERTS_SMP	Process *tracer;#endif	unsigned size;	unsigned retval_size;#ifdef DEBUG	Eterm* limit;#endif	ASSERT(is_internal_pid(*tracer_pid)	       && internal_pid_index(*tracer_pid) < erts_max_processes);#ifndef ERTS_SMP	tracer = process_tab[internal_pid_index(*tracer_pid)];	if (INVALID_PID(tracer, *tracer_pid)	    || (tracer->trace_flags & F_TRACER) == 0) {	    *tracee_flags &= ~TRACEE_FLAGS;	    *tracer_pid = NIL;	    return;	}#endif		retval_size = size_object(retval);	size = 6 + 4 + retval_size;	if (*tracee_flags & F_TIMESTAMP) {	    size += 1+4;	}#ifdef ERTS_SMP	bp = new_message_buffer(size);	hp = bp->mem;	off_heap = &bp->off_heap;#else	hp = erts_alloc_message_heap(size, &bp, &off_heap, tracer, 0);#endif#ifdef DEBUG	limit = hp + size;#endif	/*	 * Build the trace tuple and put it into receive queue of the tracer process.	 */		mfa = TUPLE3(hp, mod, name, make_small(arity));	hp += 4;	retval = copy_struct(retval, retval_size, &hp, off_heap);	mess = TUPLE5(hp, am_trace, p->id/* Local pid */, am_return_from, mfa, retval);	hp += 6;	erts_smp_mtx_lock(&smq_mtx);	if (*tracee_flags & F_TIMESTAMP) {	    hp = patch_ts(mess, hp);	}	ASSERT(hp == limit);#ifdef ERTS_SMP	enqueue_sys_msg_unlocked(SYS_MSG_TYPE_TRACE,				 tracee, *tracer_pid, mess, bp);	erts_smp_mtx_unlock(&smq_mtx);#else	erts_queue_message(tracer, 0, bp, mess, NIL);#endif    }}/* Send {trace_ts, Pid, exception_from, {Mod, Name, Arity}, {Class,Value},  *       Timestamp} * or   {trace, Pid, exception_from, {Mod, Name, Arity}, {Class,Value},  *       Timestamp} * * Where Class is atomic but Value is any term. */voiderts_trace_exception(Process* p, Eterm mfa[3], Eterm class, Eterm value, 		     Eterm *tracer_pid){    Eterm* hp;    Eterm mfa_tuple;    Eterm cv;    Eterm mess;    Uint meta_flags, *tracee_flags;#ifdef ERTS_SMP    Eterm tracee;#endif        ASSERT(tracer_pid);    if (*tracer_pid == am_true) {	/* Breakpoint trace enabled without specifying tracer =>	 *   use process tracer and flags	 */	tracer_pid = &p->tracer_proc;    }    if (is_nil(*tracer_pid)) {	/* Trace disabled */	return;    }    ASSERT(is_internal_pid(*tracer_pid) || is_internal_port(*tracer_pid));    if (*tracer_pid == p->id) {	/* Do not generate trace messages to oneself */	return;    }    if (tracer_pid == &p->tracer_proc) {	/* Tracer specified in process structure =>	 *   non-breakpoint trace =>	 *     use process flags	 */	tracee_flags = &p->trace_flags;#ifdef ERTS_SMP	tracee = p->id;#endif	if (! (*tracee_flags & F_TRACE_CALLS)) {	    return;	}    } else {	/* Tracer not specified in process structure =>	 *   tracer specified in breakpoint =>	 *     meta trace =>	 *       use fixed flag set instead of process flags	 */	    	meta_flags = F_TRACE_CALLS | F_TIMESTAMP;	tracee_flags = &meta_flags;#ifdef ERTS_SMP	tracee = NIL;#endif    }        if (is_internal_port(*tracer_pid)) {	Eterm local_heap[4+3+6+5];	hp = local_heap;	mfa_tuple = TUPLE3(hp, mfa[0], mfa[1], make_small(mfa[2]));	hp += 4;	cv = TUPLE2(hp, class, value);	hp += 3;	mess = TUPLE5(hp, am_trace, p->id, am_exception_from, mfa_tuple, cv);	hp += 6;	ASSERT((hp - local_heap)*sizeof(*hp) <= sizeof(local_heap));	erts_smp_mtx_lock(&smq_mtx);	if (*tracee_flags & F_TIMESTAMP) {	    hp = patch_ts(mess, hp); /* hp += 5 */	    ASSERT((hp - local_heap)*sizeof(*hp) == sizeof(local_heap));	}	send_to_port(p, mess, tracer_pid, tracee_flags);	erts_smp_mtx_unlock(&smq_mtx);    } else {	ErlHeapFragment *bp;	ErlOffHeap *off_heap;#ifndef ERTS_SMP	Process *tracer;#endif	unsigned size;	unsigned value_size;#ifdef DEBUG	Eterm* limit;#endif	ASSERT(is_internal_pid(*tracer_pid)	       && internal_pid_index(*tracer_pid) < erts_max_processes);#ifndef ERTS_SMP	tracer = process_tab[internal_pid_index(*tracer_pid)];	if (INVALID_PID(tracer, *tracer_pid)	    || (tracer->trace_flags & F_TRACER) == 0) {	    *tracee_flags &= ~TRACEE_FLAGS;	    *tracer_pid = NIL;	    return;	}#endif		value_size = size_object(value);	size = 6 + 4 + 3 + value_size;	if (*tracee_flags & F_TIMESTAMP) {	    size += 1+4;	}#ifdef ERTS_SMP	bp = new_message_buffer(size);	hp = bp->mem;	off_heap = &bp->off_heap;#else	hp = erts_alloc_message_heap(size, &bp, &off_heap, tracer, 0);#endif#ifdef DEBUG	limit = hp + size;#endif	/*	 * Build the trace tuple and put it into receive queue of the tracer process.	 */		mfa_tuple = TUPLE3(hp, mfa[0], mfa[1], make_small(mfa[2]));	hp += 4;	value = copy_struct(value, value_size, &hp, off_heap);	cv = TUPLE2(hp, class, value);	hp += 3;	mess = TUPLE5(hp, am_trace, p->id/* Local pid */, 		      am_exception_from, mfa_tuple, cv);	hp += 6;	erts_smp_mtx_lock(&smq_mtx);	if (*tracee_flags & F_TIMESTAMP) {	    hp = patch_ts(mess, hp);	}	ASSERT(hp == limit);#ifdef ERTS_SMP	enqueue_sys_msg_unlocked(SYS_MSG_TYPE_TRACE,				 tracee, *tracer_pid, mess, bp);	erts_smp_mtx_unlock(&smq_mtx);#else	erts_queue_message(tracer, 0, bp, mess, NIL);#endif    }}/* * This function implements the new call trace. * * Send {trace_ts, Pid, call, {Mod, Func, A}, PamResult, Timestamp} * or   {trace_ts, Pid, call, {Mod, Func, A}, Timestamp} * or   {trace, Pid, call, {Mod, Func, A}, PamResult} * or   {trace, Pid, call, {Mod, Func, A} * * where 'A' is arity or argument list depending on trace flag 'arity'. * * If *tracer_pid is am_true, it is a breakpoint trace that shall use * the process tracer, if it is NIL no trace message is generated,  * if it is a pid or port we do a meta trace. */Uint32erts_call_trace(Process* p, Eterm mfa[3], Binary *match_spec, 		Eterm* args, int local, Eterm *tracer_pid){    Eterm* hp;    Eterm mfa_tuple;    int arity;    int i;    Uint32 return_flags;    Eterm pam_result = am_true;    Eterm mess;    Uint meta_flags, *tracee_flags;#ifdef ERTS_SMP    Eterm tracee;#endif        ASSERT(tracer_pid);    if (*tracer_pid == am_true) {	/* Breakpoint trace enabled without specifying tracer =>	 *   use process tracer and flags	 */	tracer_pid = &p->tracer_proc;    }     if (is_nil(*tracer_pid)) {	/* Trace disabled */	return 0;    }    ASSERT(is_internal_pid(*tracer_pid) || is_internal_port(*tracer_pid));    if (*tracer_pid == p->id) {	/* Do not generate trace messages to oneself */	return 0;    }    if (tracer_pid == &p->tracer_proc) {	/* Tracer specified in process structure =>	 *   non-breakpoint trace =>	 *     use process flags	 */	tracee_flags = &p->trace_flags;#ifdef ERTS_SMP	tracee = p->id;#endif    } else {	/* Tracer not specified in process structure =>	 *   tracer specified in breakpoint =>	 *     meta trace =>	 *       use fixed flag set instead of process flags	 */	    	if (p->trace_flags & F_SENSITIVE) {	    /* No trace messages for sensitive processes. */	    return 0;	}	meta_flags = F_TRACE_CALLS | F_TIMESTAMP;	tracee_flags = &meta_flags;#ifdef ERTS_SMP	tracee = NIL;#endif    }    if (is_internal_port(*tracer_pid)) {	Eterm local_heap[64+MAX_ARG];	hp = local_heap;	if (!erts_is_valid_tracer_port(*tracer_pid)) {#ifdef ERTS_SMP	    ASSERT(is_nil(tracee) || tracer_pid == &p->tracer_proc);	    if (is_not_nil(tracee))		erts_smp_proc_lock(p, ERTS_PROC_LOCKS_ALL_MINOR);#endif	    *tracee_flags &= ~TRACEE_FLAGS;	    *tracer_pid = NIL;#ifdef ERTS_SMP	    if (is_not_nil(tracee))		erts_smp_proc_unlock(p, ERTS_PROC_LOCKS_ALL_MINOR);#endif	    return 0;	}		/*	 * If there is a PAM program, run it.  Return if it fails.	 *	 * Some precedence rules:	 * 	 * - No proc flags, e.g 'silent' or 'return_to' 	 *   has any effect on meta trace.	 * - The 'silent' process trace flag silences all call 	 *   related messages, e.g 'call', 'return_to' and 'return_from'.	 * - The {message,_} PAM function does not affect {return_trace}.	 * - The {message,false} PAM function shall give the same	 *   'call' trace message as no PAM match.	 * - The {message,true} PAM function shall give the same	 *   'call' trace message as a nonexistent PAM program.	 */		/* BEGIN this code should be the same for port and pid trace */	return_flags = 0;	arity = mfa[2];	if (match_spec) {	    pam_result = erts_match_set_run(p, match_spec, args, arity,					    &return_flags);	    if (is_non_value(pam_result)) {		erts_match_set_release_result(p);		return 0;	    }	}	if (tracee_flags == &meta_flags) {	    /* Meta trace */	    if (pam_result == am_false) {		erts_match_set_release_result(p);		return return_flags;	    }	} else {	    /* Non-meta trace */	    if (*tracee_flags & F_TRACE_SILENT) { 		erts_match_set_release_result(p);		return 0;	    }	    if (pam_result == am_false) {		erts_match_set_release_result(p);		return return_flags;	    }	    if (local && (*tracee_flags & F_TRACE_RETURN_TO)) {		return_flags |= MATCH_SET_RETURN_TO_TRACE;	    }	}	/* END this code should be the same for port and pid trace */		/*	 * Build the the {M,F,A} tuple in the local heap. 	 * (A is arguments or arity.)	 */		if (*tracee_flags & F_TRACE_ARITY_ONLY) {	    mfa_tuple = make_small(arity);	} else {	    mfa_tuple = NIL;	    for (i = arity-1; i >= 0; i--) {		mfa_tuple = CONS(hp, args[i], mfa_tuple);		hp += 2;	    }	}	mfa_tuple = TUPLE3(hp, mfa[0], mfa[1], mfa_tuple);	hp += 4;		/*	 * Build the trace tuple and send it to the port.	 */		mess = TUPLE4(hp, am_trace, p->id, am_call, mfa_tuple);	hp += 5;	if (pam_result != am_true) {	    hp[-5] = make_arityval(5);	    *hp++ = pam_result;	}	erts_smp_mtx_lock(&smq_mtx);	if (*tracee_flags & F_TIMESTAMP) {	    hp = patch_ts(mess, hp);	}	send_to_port(p, mess, tracer_pid, tracee_flags);	erts_smp_mtx_unlock(&smq_mtx);	erts_match_set_release_result(p);	return *tracer_pid == NIL ? 0 : return_flags;    } else {#ifdef ERTS_SMP	Eterm tpid;#endif	ErlHeapFragment *bp;	ErlOffHeap *off_heap;	Process *tracer;	unsigned size;	unsigned sizes[256];	unsigned pam_result_size = 0;	int invalid_tracer;#ifdef DEBUG	Eterm* limit;#endif	ASSERT(is_internal_pid(*tracer_pid)

⌨️ 快捷键说明

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