diff options
55 files changed, 788 insertions, 522 deletions
diff --git a/erts/doc/src/erl.xml b/erts/doc/src/erl.xml index e13470c83c..c499fc8081 100644 --- a/erts/doc/src/erl.xml +++ b/erts/doc/src/erl.xml @@ -632,6 +632,15 @@ <p>Sets the initial process dictionary size of processes to the size <c><![CDATA[Size]]></c>.</p> </item> + <tag><marker id="+hmqd"><c>+hmqd off_heap|on_heap|mixed</c></marker></tag> + <item><p> + Sets the default value for the process flag + <c>message_queue_data</c>. If <c>+hmqd</c> is not + passed, <c>mixed</c> will be the default. For more information, + see the documentation of + <seealso marker="erlang#process_flag_message_queue_data"><c>process_flag(message_queue_data, + MQD)</c></seealso>. + </p></item> <tag><c><![CDATA[+K true | false]]></c></tag> <item> <p>Enables or disables the kernel poll functionality if @@ -1361,21 +1370,6 @@ <seealso marker="kernel:error_logger#warning_map/0">error_logger(3)</seealso> for further information.</p> </item> - <tag><c><![CDATA[+xFlag Value]]></c></tag> - <item> - <p>Default process flag settings.</p> - <taglist> - <tag><marker id="+xmqd"><c>+xmqd off_heap|on_heap|mixed</c></marker></tag> - <item><p> - Sets the default value for the process flag - <c>message_queue_data</c>. If <c>+xmqd</c> is not - passed, <c>mixed</c> will be the default. For more information, - see the documentation of - <seealso marker="erlang#process_flag_message_queue_data"><c>process_flag(message_queue_data, - MQD)</c></seealso>. - </p></item> - </taglist> - </item> <tag><c><![CDATA[+zFlag Value]]></c></tag> <item> <p>Miscellaneous flags.</p> diff --git a/erts/doc/src/erlang.xml b/erts/doc/src/erlang.xml index 423ccdf98f..3276bc34b0 100644 --- a/erts/doc/src/erlang.xml +++ b/erts/doc/src/erlang.xml @@ -4371,7 +4371,7 @@ os_prompt% </pre> </taglist> <p> The default <c>message_queue_data</c> process flag is determined - by the <seealso marker="erl#+xmqd"><c>+xmqd</c></seealso> + by the <seealso marker="erl#+hmqd"><c>+hmqd</c></seealso> <c>erl</c> command line argument. </p> <p> @@ -4702,7 +4702,7 @@ os_prompt% </pre> detailed information about garbage collection for this process. The content of <c><anno>GCInfo</anno></c> can be changed without prior notice. - See <seealso marker="#gc_start">gc_start</seealso> in + See <seealso marker="#gc_minor_start">gc_minor_start</seealso> in <seealso marker="#trace/3">erlang:trace/3</seealso> for details about what each item means. </p> @@ -4878,7 +4878,9 @@ os_prompt% </pre> <tag><c>{total_heap_size, <anno>Size</anno>}</c></tag> <item> <p><c><anno>Size</anno></c> is the total size, in words, of all heap - fragments of the process. This includes the process stack.</p> + fragments of the process. This includes the process stack and + any unreceived messages that are considered to be part of the + heap. </p> </item> <tag><c>{trace, <anno>InternalTraceFlags</anno>}</c></tag> <item> @@ -5709,7 +5711,7 @@ true</pre> flag. <c><anno>MQD</anno></c> should be either <c>off_heap</c>, <c>on_heap</c>, or <c>mixed</c>. The default <c>message_queue_data</c> process flag is determined by the - <seealso marker="erl#+xmqd"><c>+xmqd</c></seealso> <c>erl</c> + <seealso marker="erl#+hmqd"><c>+hmqd</c></seealso> <c>erl</c> command line argument. For more information, see the documentation of <seealso marker="#process_flag_message_queue_data"><c>process_flag(message_queue_data, @@ -7388,7 +7390,7 @@ ok <p>Returns the default value of the <c>message_queue_data</c> process flag which is either <c>off_heap</c>, <c>on_heap</c>, or <c>mixed</c>. This default is set by the <c>erl</c> command line argument - <seealso marker="erl#+xmqd"><c>+xmqd</c></seealso>. For more information on the + <seealso marker="erl#+hmqd"><c>+hmqd</c></seealso>. For more information on the <c>message_queue_data</c> process flag, see documentation of <seealso marker="#process_flag_message_queue_data"><c>process_flag(message_queue_data, MQD)</c></seealso>.</p> @@ -7966,7 +7968,7 @@ ok <c>stack_size</c>, <c>mbuf_size</c>, <c>old_heap_size</c>, and <c>old_heap_block_size</c>. These tuples are explained in the description of trace message - <seealso marker="#gc_start">gc_start</seealso> (see + <seealso marker="#gc_minor_start">gc_minor_start</seealso> (see <seealso marker="#trace/3">erlang:trace/3</seealso>). New tuples can be added, and the order of the tuples in the <c>Info</c> list can be changed at any time without @@ -8556,7 +8558,7 @@ timestamp() -> <tag><c>garbage_collection</c></tag> <item> <p>Traces garbage collections of processes.</p> - <p>Message tags: <c><seealso marker="#trace_3_trace_messages_gc_start">gc_start</seealso></c> and <c><seealso marker="#trace_3_trace_messages_gc_end">gc_end</seealso></c>.</p> + <p>Message tags: <c><seealso marker="#trace_3_trace_messages_gc_minor_start">gc_minor_start</seealso></c> and <c><seealso marker="#trace_3_trace_messages_gc_minor_end">gc_minor_end</seealso></c>.</p> </item> <tag><c>timestamp</c></tag> <item> @@ -8637,8 +8639,8 @@ timestamp() -> <p>Specifies that a tracer module should be called instead of sending a trace message. The tracer module can then ignore or change the trace message. For more details - on how to write a tracer module see <seealso marker="erl_tracer"> - erl_tracer</seealso> + on how to write a tracer module see + <seealso marker="erts:erl_tracer"><c>erl_tracer</c></seealso> </p> </item> </taglist> @@ -8880,12 +8882,12 @@ timestamp() -> </p> </item> <tag> - <marker id="trace_3_trace_messages_gc_start"></marker> - <c>{trace, Pid, gc_start, Info}</c> + <marker id="trace_3_trace_messages_gc_minor_start"></marker> + <c>{trace, Pid, gc_minor_start, Info}</c> </tag> <item> - <marker id="gc_start"></marker> - <p>Sent when garbage collection is about to be started. + <marker id="gc_minor_start"></marker> + <p>Sent when a young garbage collection is about to be started. <c>Info</c> is a list of two-element tuples, where the first element is a key, and the second is the value. Do not depend on any order of the tuples. @@ -8925,15 +8927,32 @@ timestamp() -> <p>All sizes are in words.</p> </item> <tag> - <marker id="trace_3_trace_messages_gc_end"></marker> - <c>{trace, Pid, gc_end, Info}</c> + <marker id="trace_3_trace_messages_gc_minor_end"></marker> + <c>{trace, Pid, gc_minor_end, Info}</c> </tag> <item> - <p>Sent when garbage collection is finished. <c>Info</c> - contains the same kind of list as in message <c>gc_start</c>, + <p>Sent when young garbage collection is finished. <c>Info</c> + contains the same kind of list as in message <c>gc_minor_start</c>, but the sizes reflect the new sizes after garbage collection.</p> </item> + <tag> + <marker id="trace_3_trace_messages_gc_major_start"></marker> + <c>{trace, Pid, gc_major_start, Info}</c> + </tag> + <item> + <p>Sent when fullsweep garbage collection is about to be started. <c>Info</c> + contains the same kind of list as in message <c>gc_minor_start</c>.</p> + </item> + <tag> + <marker id="trace_3_trace_messages_gc_major_end"></marker> + <c>{trace, Pid, gc_major_end, Info}</c> + </tag> + <item> + <p>Sent when fullsweep garbage collection is finished. <c>Info</c> + contains the same kind of list as in message <c>gc_minor_start</c> + but the sizes reflect the new sizes after a fullsweep garbage collection.</p> + </item> </taglist> <p>If the tracing process/port dies or the tracer module returns <c>remove</c>, the flags are silently removed.</p> @@ -8989,7 +9008,7 @@ timestamp() -> <c>erlang:trace_delivered(<anno>Tracee</anno>)</c> resides on. The special <c><anno>Tracee</anno></c> atom <c>all</c> denotes all processes that currently are traced in the node.</p> - <p>When used together with an <seealso marker="#erl_tracer"> + <p>When used together with an <seealso marker="erts:erl_tracer"> Tracer Module</seealso> any message sent in the trace callback is guaranteed to have reached it's recipient before the <c>trace_delivered</c> message is sent.</p> diff --git a/erts/emulator/beam/beam_bp.h b/erts/emulator/beam/beam_bp.h index bb171be8a6..08641b86d6 100644 --- a/erts/emulator/beam/beam_bp.h +++ b/erts/emulator/beam/beam_bp.h @@ -173,19 +173,7 @@ void erts_clear_time_trace_bif(BeamInstr *pc); BeamInstr *erts_find_local_func(Eterm mfa[3]); -ERTS_GLB_INLINE Uint erts_bp_sched2ix(void); - #if ERTS_GLB_INLINE_INCL_FUNC_DEF -ERTS_GLB_INLINE Uint erts_bp_sched2ix(void) -{ -#ifdef ERTS_SMP - ErtsSchedulerData *esdp; - esdp = erts_get_scheduler_data(); - return esdp->no - 1; -#else - return 0; -#endif -} extern erts_smp_atomic32_t erts_active_bp_index; extern erts_smp_atomic32_t erts_staging_bp_index; diff --git a/erts/emulator/beam/bif.c b/erts/emulator/beam/bif.c index ed5b2983dd..c38d031ab8 100644 --- a/erts/emulator/beam/bif.c +++ b/erts/emulator/beam/bif.c @@ -1736,7 +1736,9 @@ BIF_RETTYPE process_flag_2(BIF_ALIST_2) ERTS_TRACE_FLAGS(BIF_P) &= ~F_SENSITIVE; } erts_smp_proc_unlock(BIF_P, ERTS_PROC_LOCKS_ALL_MINOR); - BIF_RET(old_value); + /* make sure to bump all reds so that we get + rescheduled immediately so setting takes effect */ + BIF_RET2(old_value, CONTEXT_REDS); } else if (BIF_ARG_1 == am_monitor_nodes) { /* diff --git a/erts/emulator/beam/break.c b/erts/emulator/beam/break.c index 4f5e80f2e5..d02c6828f9 100644 --- a/erts/emulator/beam/break.c +++ b/erts/emulator/beam/break.c @@ -347,8 +347,11 @@ print_process_info(int to, void *to_arg, Process *p) static void print_garb_info(int to, void *to_arg, Process* p) { +#ifdef ERTS_SMP /* ERTS_SMP: A scheduler is probably concurrently doing gc... */ -#ifndef ERTS_SMP + if (!ERTS_IS_CRASH_DUMPING) + return; +#endif 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); @@ -356,7 +359,6 @@ print_garb_info(int to, void *to_arg, Process* p) 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 } void diff --git a/erts/emulator/beam/erl_async.c b/erts/emulator/beam/erl_async.c index 4d6d699d9f..84254af0c2 100644 --- a/erts/emulator/beam/erl_async.c +++ b/erts/emulator/beam/erl_async.c @@ -283,10 +283,10 @@ static ERTS_INLINE void async_add(ErtsAsync *a, ErtsAsyncQ* q) erts_thr_q_enqueue(&q->thr_q, a); #ifdef USE_LTTNG_VM_TRACEPOINTS - if (LTTNG_ENABLED(aio_pool_add)) { + if (LTTNG_ENABLED(aio_pool_put)) { lttng_decl_portbuf(port_str); lttng_portid_to_str(a->port, port_str); - LTTNG2(aio_pool_add, port_str, -1); + LTTNG2(aio_pool_put, port_str, -1); } #endif #ifdef USE_VM_PROBES diff --git a/erts/emulator/beam/erl_bif_info.c b/erts/emulator/beam/erl_bif_info.c index c9741b361f..99fe847ba2 100644 --- a/erts/emulator/beam/erl_bif_info.c +++ b/erts/emulator/beam/erl_bif_info.c @@ -1359,9 +1359,10 @@ process_info_aux(Process *BIF_P, total_heap_size += rp->mbuf_sz; - for (mp = rp->msg.first; mp; mp = mp->next) - if (mp->data.attached) - total_heap_size += erts_msg_attached_data_size(mp); + if (rp->flags & F_ON_HEAP_MSGQ) + for (mp = rp->msg.first; mp; mp = mp->next) + if (mp->data.attached) + total_heap_size += erts_msg_attached_data_size(mp); (void) erts_bld_uint(NULL, &hsz, total_heap_size); hp = HAlloc(BIF_P, hsz); diff --git a/erts/emulator/beam/erl_gc.c b/erts/emulator/beam/erl_gc.c index df5d0f4918..cf54f1e384 100644 --- a/erts/emulator/beam/erl_gc.c +++ b/erts/emulator/beam/erl_gc.c @@ -3009,10 +3009,30 @@ erts_process_gc_info(Process *p, Uint *sizep, Eterm **hpp) }; Eterm res = THE_NON_VALUE; + ErtsMessage *mp; ERTS_CT_ASSERT(sizeof(values)/sizeof(*values) == sizeof(tags)/sizeof(*tags)); ERTS_CT_ASSERT(sizeof(values)/sizeof(*values) == ERTS_PROCESS_GC_INFO_MAX_TERMS); + if (p->abandoned_heap) { + Eterm *htop, *heap; + ERTS_GET_ORIG_HEAP(p, heap, htop); + values[3] = HIGH_WATER(p) - heap; + values[6] = htop - heap; + } + + if (p->flags & F_ON_HEAP_MSGQ) { + /* If on heap messages in the internal queue are counted + as being part of the heap, so we have to add them to the + am_mbuf_size value. process_info(total_heap_size) should + be the same as adding old_heap_block_size + heap_block_size + + mbuf_size. + */ + for (mp = p->msg.first; mp; mp = mp->next) + if (mp->data.attached) + values[2] += erts_msg_attached_data_size(mp); + } + res = erts_bld_atom_uword_2tup_list(hpp, sizep, sizeof(values)/sizeof(*values), diff --git a/erts/emulator/beam/erl_init.c b/erts/emulator/beam/erl_init.c index dec9bdfedc..2fd1eeb785 100644 --- a/erts/emulator/beam/erl_init.c +++ b/erts/emulator/beam/erl_init.c @@ -578,6 +578,8 @@ void erts_usage(void) VH_DEFAULT_SIZE); erts_fprintf(stderr, "-hpds size initial process dictionary size (default %d)\n", erts_pd_initial_size); + erts_fprintf(stderr, "-hmqd val set default message queue data flag for processes,\n"); + erts_fprintf(stderr, " valid values are: off_heap | on_heap | mixed\n"); /* erts_fprintf(stderr, "-i module set the boot module (default init)\n"); */ @@ -655,8 +657,6 @@ void erts_usage(void) erts_fprintf(stderr, "-W<i|w|e> set error logger warnings mapping,\n"); erts_fprintf(stderr, " see error_logger documentation for details\n"); - erts_fprintf(stderr, "-xmqd val set default message queue data flag for processes,\n"); - erts_fprintf(stderr, " valid values are: off_heap | on_heap | mixed\n"); erts_fprintf(stderr, "-zdbbl size set the distribution buffer busy limit in kilobytes\n"); erts_fprintf(stderr, " valid range is [1-%d]\n", INT_MAX/1024); erts_fprintf(stderr, "-zdntgc time set delayed node table gc in seconds\n"); @@ -1487,6 +1487,7 @@ erl_start(int argc, char **argv) * h|ms - min_heap_size * h|mbs - min_bin_vheap_size * h|pds - erts_pd_initial_size + * h|mqd - message_queue_data * */ if (has_prefix("mbs", sub_param)) { @@ -1512,6 +1513,23 @@ erl_start(int argc, char **argv) } VERBOSE(DEBUG_SYSTEM, ("using initial process dictionary size %d\n", erts_pd_initial_size)); + } else if (has_prefix("mqd", sub_param)) { + arg = get_arg(sub_param+3, argv[i+1], &i); + if (sys_strcmp(arg, "mixed") == 0) + erts_default_spo_flags &= ~(SPO_ON_HEAP_MSGQ|SPO_OFF_HEAP_MSGQ); + else if (sys_strcmp(arg, "on_heap") == 0) { + erts_default_spo_flags &= ~SPO_OFF_HEAP_MSGQ; + erts_default_spo_flags |= SPO_ON_HEAP_MSGQ; + } + else if (sys_strcmp(arg, "off_heap") == 0) { + erts_default_spo_flags &= ~SPO_ON_HEAP_MSGQ; + erts_default_spo_flags |= SPO_OFF_HEAP_MSGQ; + } + else { + erts_fprintf(stderr, + "Invalid message_queue_data flag: %s\n", arg); + erts_usage(); + } } else { /* backward compatibility */ arg = get_arg(argv[i]+2, argv[i+1], &i); @@ -2047,32 +2065,6 @@ erl_start(int argc, char **argv) } break; - case 'x': { - char *sub_param = argv[i]+2; - if (has_prefix("mqd", sub_param)) { - arg = get_arg(sub_param+3, argv[i+1], &i); - if (sys_strcmp(arg, "mixed") == 0) - erts_default_spo_flags &= ~(SPO_ON_HEAP_MSGQ|SPO_OFF_HEAP_MSGQ); - else if (sys_strcmp(arg, "on_heap") == 0) { - erts_default_spo_flags &= ~SPO_OFF_HEAP_MSGQ; - erts_default_spo_flags |= SPO_ON_HEAP_MSGQ; - } - else if (sys_strcmp(arg, "off_heap") == 0) { - erts_default_spo_flags &= ~SPO_ON_HEAP_MSGQ; - erts_default_spo_flags |= SPO_OFF_HEAP_MSGQ; - } - else { - erts_fprintf(stderr, - "Invalid message_queue_data flag: %s\n", arg); - erts_usage(); - } - } else { - erts_fprintf(stderr, "bad -x option %s\n", argv[i]); - erts_usage(); - } - break; - } - case 'z': { char *sub_param = argv[i]+2; diff --git a/erts/emulator/beam/erl_process.h b/erts/emulator/beam/erl_process.h index 61acf5924b..1c01d705a7 100644 --- a/erts/emulator/beam/erl_process.h +++ b/erts/emulator/beam/erl_process.h @@ -925,7 +925,6 @@ struct process { Eterm* stop; /* Stack top */ Eterm* heap; /* Heap start */ Eterm* hend; /* Heap end */ - Eterm* abandoned_heap; Uint heap_sz; /* Size of heap in words */ Uint min_heap_size; /* Minimum size of heap (in words). */ Uint min_vheap_size; /* Minimum size of virtual heap (in words). */ @@ -941,6 +940,16 @@ struct process { #endif /* + * Moved to after "struct hipe_process_state hipe", as a temporary fix for + * LLVM hard-coding offsetof(struct process, hipe.nstack) (sic!) + * (see void X86FrameLowering::adjustForHiPEPrologue(...) in + * lib/Target/X86/X86FrameLowering.cpp). + * + * Used to be below "Eterm* hend". + */ + Eterm* abandoned_heap; + + /* * Saved x registers. */ Uint arity; /* Number of live argument registers (only valid diff --git a/erts/emulator/beam/erl_trace.c b/erts/emulator/beam/erl_trace.c index 56899f574a..128696270b 100644 --- a/erts/emulator/beam/erl_trace.c +++ b/erts/emulator/beam/erl_trace.c @@ -658,6 +658,7 @@ do { \ # define GET_NOW(m, s, u) do {get_now(m, s, u);} while (0) #endif + static void write_sys_msg_to_port(Eterm unused_to, Port* trace_port, @@ -1737,41 +1738,6 @@ profile_scheduler(Eterm scheduler_id, Eterm state) { } -void -profile_scheduler_q(Eterm scheduler_id, Eterm state, Eterm no_schedulers, Uint Ms, Uint s, Uint us) { - Eterm *hp, msg, timestamp; - -#ifndef ERTS_SMP -#define LOCAL_HEAP_SIZE (4 + 7) - DeclareTmpHeapNoproc(local_heap,LOCAL_HEAP_SIZE); - UseTmpHeapNoproc(LOCAL_HEAP_SIZE); - - hp = local_heap; -#else - ErlHeapFragment *bp; - Uint hsz; - - hsz = 4 + 7; - - bp = new_message_buffer(hsz); - hp = bp->mem; -#endif - - erts_smp_mtx_lock(&smq_mtx); - - timestamp = TUPLE3(hp, make_small(Ms), make_small(s), make_small(us)); hp += 4; - msg = TUPLE6(hp, am_profile, am_scheduler, scheduler_id, state, no_schedulers, timestamp); hp += 7; -#ifndef ERTS_SMP - profile_send(NIL, msg); - UnUseTmpHeapNoproc(LOCAL_HEAP_SIZE); -#undef LOCAL_HEAP_SIZE -#else - enqueue_sys_msg_unlocked(SYS_MSG_TYPE_SYSPROF, NIL, NIL, msg, bp); -#endif - erts_smp_mtx_unlock(&smq_mtx); - -} - /* Port profiling */ void @@ -1935,7 +1901,10 @@ trace_port_receive(Port *t_p, Eterm caller, Eterm what, ...) } data = TUPLE2(hp, caller, data); - send_to_tracer_nif(NULL, &t_p->common, t_p->common.id, tnif, TRACE_FUN_T_RECEIVE, + hp += 3; + ASSERT(hp <= (local_heap + LOCAL_HEAP_SIZE) || orig_hp); + send_to_tracer_nif(NULL, &t_p->common, t_p->common.id, tnif, + TRACE_FUN_T_RECEIVE, am_receive, data, THE_NON_VALUE); if (bptr && erts_refc_dectest(&bptr->refc, 1) == 0) diff --git a/erts/emulator/beam/erlang_lttng.h b/erts/emulator/beam/erlang_lttng.h index 43ceeda671..12f68e477b 100644 --- a/erts/emulator/beam/erlang_lttng.h +++ b/erts/emulator/beam/erlang_lttng.h @@ -218,13 +218,13 @@ TRACEPOINT_EVENT( driver_stop, TP_ARGS( char*, pid, - char*, driver, - char*, port + char*, port, + char*, driver ), TP_FIELDS( ctf_string(pid, pid) - ctf_string(driver, driver) ctf_string(port, port) + ctf_string(driver, driver) ) ) @@ -324,7 +324,7 @@ TRACEPOINT_EVENT( TRACEPOINT_EVENT( com_ericsson_otp, - aio_pool_add, + aio_pool_put, TP_ARGS( char*, port, int, length diff --git a/erts/emulator/beam/io.c b/erts/emulator/beam/io.c index b14ca77a04..5c2595c69d 100644 --- a/erts/emulator/beam/io.c +++ b/erts/emulator/beam/io.c @@ -3861,7 +3861,7 @@ terminate_port(Port *prt) lttng_decl_procbuf(proc_str); lttng_pid_to_str(connected_id, proc_str); lttng_port_to_str(prt, port_str); - LTTNG3(driver_stop, proc_str, drv->name, port_str); + LTTNG3(driver_stop, proc_str, port_str, drv->name); } #endif diff --git a/erts/emulator/beam/utils.c b/erts/emulator/beam/utils.c index b280995488..68006e7ef3 100644 --- a/erts/emulator/beam/utils.c +++ b/erts/emulator/beam/utils.c @@ -71,41 +71,6 @@ #define HAVE_MALLOPT 0 #endif -/* profile_scheduler mini message queue */ - -typedef struct { - Uint scheduler_id; - Uint no_schedulers; - Uint Ms; - Uint s; - Uint us; - Eterm state; -} profile_sched_msg; - -typedef struct { - profile_sched_msg msg[2]; - Uint n; -} profile_sched_msg_q; - -#ifdef ERTS_SMP - -#if 0 /* Unused */ -static void -dispatch_profile_msg_q(profile_sched_msg_q *psmq) -{ - int i = 0; - profile_sched_msg *msg = NULL; - ASSERT(psmq != NULL); - for (i = 0; i < psmq->n; i++) { - msg = &(psmq->msg[i]); - profile_scheduler_q(make_small(msg->scheduler_id), msg->state, am_undefined, msg->Ms, msg->s, msg->us); - } -} -#endif - -#endif - - Eterm* erts_heap_alloc(Process* p, Uint need, Uint xtra) { diff --git a/erts/emulator/nifs/common/erl_tracer_nif.c b/erts/emulator/nifs/common/erl_tracer_nif.c index 1bb6b940c4..8a9a1bf16c 100644 --- a/erts/emulator/nifs/common/erl_tracer_nif.c +++ b/erts/emulator/nifs/common/erl_tracer_nif.c @@ -72,8 +72,6 @@ ERL_NIF_INIT(erl_tracer, nif_funcs, load, NULL, upgrade, unload) ATOM_DECL(trace); \ ATOM_DECL(trace_ts); \ ATOM_DECL(true); \ - ATOM_DECL(gc_start); \ - ATOM_DECL(gc_end); \ ATOM_DECL(gc_minor_start); \ ATOM_DECL(gc_minor_end); \ ATOM_DECL(gc_major_start); \ @@ -130,6 +128,9 @@ static ERL_NIF_TERM enabled(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) if (!enif_is_port_alive(env, &to_port)) /* tracer is dead so we should remove this trace point */ return atom_remove; + } else { + /* The state was not a pid or a port */ + return atom_remove; } /* Only generate trace for when tracer != tracee */ diff --git a/erts/emulator/test/lttng_SUITE.erl b/erts/emulator/test/lttng_SUITE.erl index d0f6292d5b..efc79f42ed 100644 --- a/erts/emulator/test/lttng_SUITE.erl +++ b/erts/emulator/test/lttng_SUITE.erl @@ -89,8 +89,8 @@ end_per_testcase(Case, _Config) -> %% com_ericsson_otp:carrier_pool_put %% com_ericsson_otp:carrier_destroy %% com_ericsson_otp:carrier_create -%% com_ericsson_otp:aio_pool_add -%% com_ericsson_otp:aio_pool_get +%% com_ericsson_otp:aio_pool_put +%% com_ericsson_otp:aio_pool_get %% com_ericsson_otp:driver_control %% com_ericsson_otp:driver_call %% com_ericsson_otp:driver_finish @@ -151,7 +151,7 @@ t_memory_carrier(Config) -> ok end. -%% com_ericsson_otp:aio_pool_add +%% com_ericsson_otp:aio_pool_put %% com_ericsson_otp:aio_pool_get t_async_io_pool(Config) -> case have_async_threads() of @@ -168,7 +168,7 @@ t_async_io_pool(Config) -> {ok, _} = file:list_dir(Path2), Res = lttng_stop_and_view(Config), - ok = check_tracepoint("com_ericsson_otp:aio_pool_add", Res), + ok = check_tracepoint("com_ericsson_otp:aio_pool_put", Res), ok = check_tracepoint("com_ericsson_otp:aio_pool_get", Res), ok end. @@ -416,7 +416,7 @@ txt() -> "%% com_ericsson_otp:carrier_pool_put\n" "%% com_ericsson_otp:carrier_destroy\n" "%% com_ericsson_otp:carrier_create\n" - "%% com_ericsson_otp:aio_pool_add\n" + "%% com_ericsson_otp:aio_pool_put\n" "%% com_ericsson_otp:aio_pool_get\n" "%% com_ericsson_otp:driver_control\n" "%% com_ericsson_otp:driver_call\n" diff --git a/erts/emulator/test/match_spec_SUITE.erl b/erts/emulator/test/match_spec_SUITE.erl index ea973276db..6733237b20 100644 --- a/erts/emulator/test/match_spec_SUITE.erl +++ b/erts/emulator/test/match_spec_SUITE.erl @@ -597,16 +597,15 @@ ms_trace3(Config) when is_list(Config) -> end), ok. -ms_trace_dead(doc) -> - ["Test that a dead tracer is removed using ms"]; -ms_trace_dead(suite) -> []; -ms_trace_dead(Config) when is_list(Config) -> +%% Test that a dead tracer is removed using ms +ms_trace_dead(_Config) -> Self = self(), TFun = fun F() -> receive M -> Self ! M, F() end end, {Tracer, MRef} = spawn_monitor(TFun), MetaTracer = spawn_link(TFun), erlang:trace_pattern({?MODULE, f1, '_'}, - [{'_',[],[{trace,[], + [{'_',[],[{message, false}, + {trace,[], [call,{const,{tracer,Tracer}}]}]}], [{meta, MetaTracer}]), erlang:trace_pattern({?MODULE, f2, '_'}, []), @@ -623,8 +622,6 @@ ms_trace_dead(Config) when is_list(Config) -> ?MODULE:f2(3,4), TRef = erlang:trace_delivered(all), receive {trace_delivered, _, TRef} -> ok end, - receive {trace_ts, Self, call, {?MODULE, f1, _}, _} -> ok end, - receive {trace_ts, Self, call, {?MODULE, f1, _}, _} -> ok end, receive M -> ct:fail({unexpected, M}) after 10 -> ok end. %% Test that destructive operations in test bif does not really happen diff --git a/erts/emulator/test/message_queue_data_SUITE.erl b/erts/emulator/test/message_queue_data_SUITE.erl index 6efca5b39e..226462676c 100644 --- a/erts/emulator/test/message_queue_data_SUITE.erl +++ b/erts/emulator/test/message_queue_data_SUITE.erl @@ -21,7 +21,7 @@ -module(message_queue_data_SUITE). -export([all/0, suite/0]). --export([basic/1, process_info_messages/1]). +-export([basic/1, process_info_messages/1, total_heap_size/1]). -export([basic_test/1]). @@ -32,7 +32,7 @@ suite() -> {timetrap, {minutes, 2}}]. all() -> - [basic, process_info_messages]. + [basic, process_info_messages, total_heap_size]. %% %% @@ -44,15 +44,15 @@ basic(Config) when is_list(Config) -> basic_test(erlang:system_info(message_queue_data)), - {ok, Node1} = start_node(Config, "+xmqd off_heap"), + {ok, Node1} = start_node(Config, "+hmqd off_heap"), ok = rpc:call(Node1, ?MODULE, basic_test, [off_heap]), stop_node(Node1), - {ok, Node2} = start_node(Config, "+xmqd on_heap"), + {ok, Node2} = start_node(Config, "+hmqd on_heap"), ok = rpc:call(Node2, ?MODULE, basic_test, [on_heap]), stop_node(Node2), - {ok, Node3} = start_node(Config, "+xmqd mixed"), + {ok, Node3} = start_node(Config, "+hmqd mixed"), ok = rpc:call(Node3, ?MODULE, basic_test, [mixed]), stop_node(Node3), @@ -190,6 +190,28 @@ process_info_messages(Config) when is_list(Config) -> ok. +total_heap_size(_Config) -> + + Fun = fun F() -> receive Pid when is_pid(Pid) -> Pid ! ok,F() end end, + + %% Test that on_heap messages grow the heap even if they are not received + OnPid = spawn_opt(Fun, [{message_queue_data, on_heap}]), + {total_heap_size, OnSize} = erlang:process_info(OnPid, total_heap_size), + [OnPid ! lists:duplicate(N,N) || N <- lists:seq(1,100)], + OnPid ! self(), receive ok -> ok end, + {total_heap_size, OnSizeAfter} = erlang:process_info(OnPid, total_heap_size), + ct:log("OnSize = ~p, OnSizeAfter = ~p",[OnSize, OnSizeAfter]), + true = OnSize < OnSizeAfter, + + %% Test that off_heap messages do not grow the heap if they are not received + OffPid = spawn_opt(Fun, [{message_queue_data, off_heap}]), + {total_heap_size, OffSize} = erlang:process_info(OffPid, total_heap_size), + [OffPid ! lists:duplicate(N,N) || N <- lists:seq(1,100)], + OffPid ! self(), receive ok -> ok end, + {total_heap_size, OffSizeAfter} = erlang:process_info(OffPid, total_heap_size), + ct:log("OffSize = ~p, OffSizeAfter = ~p",[OffSize, OffSizeAfter]), + true = OffSize == OffSizeAfter. + %% %% %% helpers diff --git a/erts/emulator/test/port_trace_SUITE.erl b/erts/emulator/test/port_trace_SUITE.erl index 41e8a316c4..bfdea0761b 100644 --- a/erts/emulator/test/port_trace_SUITE.erl +++ b/erts/emulator/test/port_trace_SUITE.erl @@ -240,19 +240,23 @@ command(Config) -> Prt ! {S, {command, <<?ECHO_DRV_NOOP:8>>}}, [{trace, Prt, 'receive', {S, {command, <<?ECHO_DRV_NOOP:8>>}}}] = flush(), + OutputMsg = <<?ECHO_DRV_NOOP:8,0:(8*512)>>, + Prt ! {S, {command, OutputMsg}}, + [{trace, Prt, 'receive', {S, {command, OutputMsg}}}] = flush(), + close(Prt, Flags), os:putenv("OUTPUTV","true"), reload_drv(Config), Prt2 = erlang:open_port({spawn, echo_drv}, [binary]), - Msg = [<<0:8>>,<<0:(8*512)>>,<<0:(8*256)>>,<<0:8>>], + OutputvMsg = [<<0:8>>,<<0:(8*512)>>,<<0:(8*256)>>,<<0:8>>], - erlang:port_command(Prt2, Msg), - [{trace, Prt2, 'receive', {S, {command, Msg}}}] = flush(), + erlang:port_command(Prt2, OutputvMsg), + [{trace, Prt2, 'receive', {S, {command, OutputvMsg}}}] = flush(), - Prt2 ! {S, {command, Msg}}, - [{trace, Prt2, 'receive', {S, {command, Msg}}}] = flush(), + Prt2 ! {S, {command, OutputvMsg}}, + [{trace, Prt2, 'receive', {S, {command, OutputvMsg}}}] = flush(), close(Prt2, Flags), @@ -274,6 +278,12 @@ control(_Config) -> [{trace, Prt, 'receive', {S, {control, {(1 bsl 32) - 1, <<?ECHO_DRV_NOOP:8, 0:8>>}}}}, {trace, Prt, send, {Prt, {control, <<0:8>>}}, S}] = flush(), + Msg = <<?ECHO_DRV_NOOP:8, 0:(8*512)>>, + Pat = lists:duplicate(512, 0), + Pat = erlang:port_control(Prt, 1, Msg), + [{trace, Prt, 'receive', {S, {control, {1, Msg}}}}, + {trace, Prt, send, {Prt, {control, <<0:(8*512)>>}}, S}] = flush(), + close(Prt, Flags), ok. @@ -331,12 +341,16 @@ call(_Config) -> Flags = [send,'receive'], {Prt, S} = trace_and_open(Flags,[binary]), - Msg = {hello, world, make_ref()}, - BinMsg = term_to_binary(Msg), + Test = fun(Msg) -> + BinMsg = term_to_binary(Msg), + + Msg = erlang:port_call(Prt, 0, Msg), + [{trace, Prt, 'receive', {S, {call, {0, BinMsg}}}}, + {trace, Prt, send, {Prt, {call, BinMsg}}, S}] = flush() + end, - Msg = erlang:port_call(Prt, 0, Msg), - [{trace, Prt, 'receive', {S, {call, {0, BinMsg}}}}, - {trace, Prt, send, {Prt, {call, BinMsg}}, S}] = flush(), + Test({hello, world, make_ref()}), + Test({hello, world, lists:seq(1,1000)}), close(Prt, Flags), diff --git a/erts/emulator/test/port_trace_SUITE_data/echo_drv.c b/erts/emulator/test/port_trace_SUITE_data/echo_drv.c index b5728bc170..b5ae9389b4 100644 --- a/erts/emulator/test/port_trace_SUITE_data/echo_drv.c +++ b/erts/emulator/test/port_trace_SUITE_data/echo_drv.c @@ -217,6 +217,8 @@ static ErlDrvSSizeT echo_drv_control(ErlDrvData drv_data, char *buf, ErlDrvSizeT len, char **rbuf, ErlDrvSizeT rlen) { + if ((len - 1) > rlen) + *rbuf = driver_alloc(len - 1); memcpy(*rbuf, buf+1, len-1); return len-1; } @@ -232,6 +234,8 @@ static ErlDrvSSizeT echo_drv_call(ErlDrvData drv_data, char **rbuf, ErlDrvSizeT rlen, unsigned int *flags) { + if ((len - command) > rlen) + *rbuf = driver_alloc(len - command); memcpy(*rbuf, buf+command, len-command); return len-command; } diff --git a/erts/emulator/test/trace_SUITE.erl b/erts/emulator/test/trace_SUITE.erl index b7f312635e..29e043dd5c 100644 --- a/erts/emulator/test/trace_SUITE.erl +++ b/erts/emulator/test/trace_SUITE.erl @@ -27,11 +27,12 @@ -export([all/0, suite/0, link_receive_call_correlation/0, receive_trace/1, link_receive_call_correlation/1, self_send/1, timeout_trace/1, send_trace/1, - procs_trace/1, dist_procs_trace/1, + procs_trace/1, dist_procs_trace/1, procs_new_trace/1, suspend/1, mutual_suspend/1, suspend_exit/1, suspender_exit/1, suspend_system_limit/1, suspend_opts/1, suspend_waiting/1, new_clear/1, existing_clear/1, set_on_spawn/1, set_on_first_spawn/1, cpu_timestamp/1, + set_on_link/1, set_on_first_link/1, system_monitor_args/1, more_system_monitor_args/1, system_monitor_long_gc_1/1, system_monitor_long_gc_2/1, system_monitor_large_heap_1/1, system_monitor_large_heap_2/1, @@ -54,7 +55,8 @@ all() -> mutual_suspend, suspend_exit, suspender_exit, suspend_system_limit, suspend_opts, suspend_waiting, new_clear, existing_clear, set_on_spawn, - set_on_first_spawn, system_monitor_args, + set_on_first_spawn, set_on_link, set_on_first_link, + system_monitor_args, more_system_monitor_args, system_monitor_long_gc_1, system_monitor_long_gc_2, system_monitor_large_heap_1, system_monitor_long_schedule, @@ -454,6 +456,34 @@ dist_procs_trace(Config) when is_list(Config) -> true = stop_node(OtherNode), ok. +%% Test trace(new, How, [procs]). +procs_new_trace(Config) when is_list(Config) -> + Self = self(), + process_flag(trap_exit, true), + %% + Proc1 = spawn_link(?MODULE, process, [Self]), + io:format("Proc1 = ~p ~n", [Proc1]), + %% + 0 = erlang:trace(new, true, [procs]), + + MFA = {?MODULE, process, [Self]}, + %% + %% spawn, link + Proc1 ! {spawn_link_please, Self, MFA}, + Proc3 = receive {spawned, Proc1, P3} -> P3 end, + receive {trace, Proc3, spawned, Proc1, MFA} -> ok end, + receive {trace, Proc3, getting_linked, Proc1} -> ok end, + io:format("Proc3 = ~p ~n", [Proc3]), + receive_nothing(), + %% + %% + %% exit (not linked to tracing process) + Reason1 = make_ref(), + Proc1 ! {exit_please, Reason1}, + receive {'EXIT', Proc1, Reason1} -> ok end, + {trace, Proc3, exit, Reason1} = receive_first_trace(), + receive_nothing(), + ok. @@ -501,6 +531,51 @@ set_on_first_spawn(Config) when is_list(Config) -> receive_nothing(), ok. +%% Tests trace(Pid, How, [set_on_link]). + +set_on_link(Config) -> + Listener = fun_spawn(fun process/0), + + %% Create and trace a process with the set_on_link flag. + %% Make sure it is traced. + Father_SOL = fun_spawn(fun process/0), + 1 = erlang:trace(Father_SOL, true, [send, set_on_link]), + true = is_send_traced(Father_SOL, Listener, sol_father), + + %% Have the process spawn of two children and test that they + %% are traced. + [Child1, Child2] = spawn_children(Father_SOL, 2), + true = is_send_traced(Child1, Listener, child1), + true = is_send_traced(Child2, Listener, child2), + + %% Second generation. + [Child11, Child12] = spawn_children(Child1, 2), + true = is_send_traced(Child11, Listener, child11), + true = is_send_traced(Child12, Listener, child12), + ok. + +%% Tests trace(Pid, How, [set_on_first_spawn]). + +set_on_first_link(Config) -> + ct:timetrap({seconds, 10}), + Listener = fun_spawn(fun process/0), + + %% Create and trace a process with the set_on_first_spawn flag. + %% Make sure it is traced. + Parent = fun_spawn(fun process/0), + 1 = erlang:trace(Parent, true, [send, set_on_first_link]), + is_send_traced(Parent, Listener, sol_father), + + %% Have the process spawn off three children and test that the + %% first is traced. + [Child1, Child2, Child3] = spawn_children(Parent, 3), + true = is_send_traced(Child1, Listener, child1), + false = is_send_traced(Child2, Listener, child2), + false = is_send_traced(Child3, Listener, child3), + receive_nothing(), + ok. + + %% Tests arguments to erlang:system_monitor/0,1,2 system_monitor_args(Config) when is_list(Config) -> diff --git a/erts/etc/common/erlexec.c b/erts/etc/common/erlexec.c index 82a0303f86..5a5021b003 100644 --- a/erts/etc/common/erlexec.c +++ b/erts/etc/common/erlexec.c @@ -150,6 +150,7 @@ static char *plush_val_switches[] = { "ms", "mbs", "pds", + "mqd", "", NULL }; @@ -160,12 +161,6 @@ static char *plusr_val_switches[] = { NULL }; -/* +x arguments with values */ -static char *plusx_val_switches[] = { - "mqd", - NULL -}; - /* +z arguments with values */ static char *plusz_val_switches[] = { "dbbl", @@ -986,20 +981,6 @@ int main(int argc, char **argv) add_Eargs(argv[i+1]); i++; break; - case 'x': - if (!is_one_of_strings(&argv[i][2], plusx_val_switches)) { - goto the_default; - } else { - if (i+1 >= argc - || argv[i+1][0] == '-' - || argv[i+1][0] == '+') - usage(argv[i]); - argv[i][0] = '-'; - add_Eargs(argv[i]); - add_Eargs(argv[i+1]); - i++; - } - break; case 'z': if (!is_one_of_strings(&argv[i][2], plusz_val_switches)) { goto the_default; @@ -1200,7 +1181,7 @@ usage_aux(void) "[+S NO_SCHEDULERS:NO_SCHEDULERS_ONLINE] " "[+SP PERCENTAGE_SCHEDULERS:PERCENTAGE_SCHEDULERS_ONLINE] " "[+T LEVEL] [+V] [+v] " - "[+W<i|w|e>] [+x DEFAULT_PROC_FLAGS] [+z MISC_OPTION] [args ...]\n"); + "[+W<i|w|e>] [+z MISC_OPTION] [args ...]\n"); exit(1); } diff --git a/erts/preloaded/ebin/erl_prim_loader.beam b/erts/preloaded/ebin/erl_prim_loader.beam Binary files differindex 77685013ae..3e82b8e20e 100644 --- a/erts/preloaded/ebin/erl_prim_loader.beam +++ b/erts/preloaded/ebin/erl_prim_loader.beam diff --git a/erts/preloaded/ebin/erl_tracer.beam b/erts/preloaded/ebin/erl_tracer.beam Binary files differindex b8f3f6d8c2..67d96d0f0d 100644 --- a/erts/preloaded/ebin/erl_tracer.beam +++ b/erts/preloaded/ebin/erl_tracer.beam diff --git a/erts/preloaded/ebin/erlang.beam b/erts/preloaded/ebin/erlang.beam Binary files differindex 15e4ca82a7..321e4e7e1b 100644 --- a/erts/preloaded/ebin/erlang.beam +++ b/erts/preloaded/ebin/erlang.beam diff --git a/erts/preloaded/ebin/erts_code_purger.beam b/erts/preloaded/ebin/erts_code_purger.beam Binary files differindex 3e95b1e42e..0c667663fd 100644 --- a/erts/preloaded/ebin/erts_code_purger.beam +++ b/erts/preloaded/ebin/erts_code_purger.beam diff --git a/erts/preloaded/ebin/erts_internal.beam b/erts/preloaded/ebin/erts_internal.beam Binary files differindex 53dd2897de..ed2e328f5b 100644 --- a/erts/preloaded/ebin/erts_internal.beam +++ b/erts/preloaded/ebin/erts_internal.beam diff --git a/erts/preloaded/ebin/init.beam b/erts/preloaded/ebin/init.beam Binary files differindex ee32066f53..23ebd2cad9 100644 --- a/erts/preloaded/ebin/init.beam +++ b/erts/preloaded/ebin/init.beam diff --git a/erts/preloaded/ebin/otp_ring0.beam b/erts/preloaded/ebin/otp_ring0.beam Binary files differindex 51a412b7f7..b63fa24848 100644 --- a/erts/preloaded/ebin/otp_ring0.beam +++ b/erts/preloaded/ebin/otp_ring0.beam diff --git a/erts/preloaded/ebin/prim_eval.beam b/erts/preloaded/ebin/prim_eval.beam Binary files differindex 45bed5cf7e..7c8fdc82c0 100644 --- a/erts/preloaded/ebin/prim_eval.beam +++ b/erts/preloaded/ebin/prim_eval.beam diff --git a/erts/preloaded/ebin/prim_file.beam b/erts/preloaded/ebin/prim_file.beam Binary files differindex c25bffb6a5..d4559bc9ed 100644 --- a/erts/preloaded/ebin/prim_file.beam +++ b/erts/preloaded/ebin/prim_file.beam diff --git a/erts/preloaded/ebin/prim_inet.beam b/erts/preloaded/ebin/prim_inet.beam Binary files differindex 85d74de065..5a0678632e 100644 --- a/erts/preloaded/ebin/prim_inet.beam +++ b/erts/preloaded/ebin/prim_inet.beam diff --git a/erts/preloaded/ebin/prim_zip.beam b/erts/preloaded/ebin/prim_zip.beam Binary files differindex 1f8fe6f03b..3d32dd8449 100644 --- a/erts/preloaded/ebin/prim_zip.beam +++ b/erts/preloaded/ebin/prim_zip.beam diff --git a/erts/preloaded/ebin/zlib.beam b/erts/preloaded/ebin/zlib.beam Binary files differindex 059585ec99..ced9f9c952 100644 --- a/erts/preloaded/ebin/zlib.beam +++ b/erts/preloaded/ebin/zlib.beam diff --git a/lib/common_test/test/ct_netconfc_SUITE.erl b/lib/common_test/test/ct_netconfc_SUITE.erl index 72c1de4023..03fbc17bd2 100644 --- a/lib/common_test/test/ct_netconfc_SUITE.erl +++ b/lib/common_test/test/ct_netconfc_SUITE.erl @@ -48,7 +48,12 @@ init_per_suite(Config) -> {error,Reason} when Reason=/={already_loaded,crypto} -> {skip, Reason}; _ -> - ct_test_support:init_per_suite(Config) + case application:load(ssh) of + {error,Reason} when Reason=/={already_loaded,ssh} -> + {skip, Reason}; + _ -> + ct_test_support:init_per_suite(Config) + end end. end_per_suite(Config) -> diff --git a/lib/common_test/test/ct_netconfc_SUITE_data/netconfc1_SUITE.erl b/lib/common_test/test/ct_netconfc_SUITE_data/netconfc1_SUITE.erl index e4062a7d62..065639dd36 100644 --- a/lib/common_test/test/ct_netconfc_SUITE_data/netconfc1_SUITE.erl +++ b/lib/common_test/test/ct_netconfc_SUITE_data/netconfc1_SUITE.erl @@ -123,15 +123,21 @@ init_per_testcase(_Case, Config) -> end_per_testcase(_Case, _Config) -> ok. +init_per_suite() -> + [{timetrap,2*?default_timeout}]. % making dsa files can be slow init_per_suite(Config) -> - case catch {crypto:start(), ssh:start()} of - {ok, ok} -> + case catch ssh:start() of + Ok when Ok==ok; Ok=={error,{already_started,ssh}} -> + ct:log("ssh started",[]), {ok, _} = netconfc_test_lib:get_id_keys(Config), netconfc_test_lib:make_dsa_files(Config), + ct:log("dsa files created",[]), Server = ?NS:start(?config(data_dir,Config)), + ct:log("netconf server started",[]), [{server,Server}|Config]; - _ -> - {skip, "Crypto and/or SSH could not be started!"} + Other -> + ct:log("could not start ssh: ~p",[Other]), + {skip, "SSH could not be started!"} end. end_per_suite(Config) -> @@ -806,7 +812,7 @@ close_while_waiting_for_chunked_data(Config) -> %% Order server to expect a get - then the process above will make %% sure the rpc-reply is sent - but only a part of it - then close. ?NS:expect('get'), - {error,closed} = ct_netconfc:get(Client,{server,[{xmlns,"myns"}],[]},2000), + {error,closed} = ct_netconfc:get(Client,{server,[{xmlns,"myns"}],[]},4000), ok. connection_crash(Config) -> diff --git a/lib/common_test/test/ct_netconfc_SUITE_data/netconfc_remote_SUITE.erl b/lib/common_test/test/ct_netconfc_SUITE_data/netconfc_remote_SUITE.erl index ae9087ce45..04bfe75187 100644 --- a/lib/common_test/test/ct_netconfc_SUITE_data/netconfc_remote_SUITE.erl +++ b/lib/common_test/test/ct_netconfc_SUITE_data/netconfc_remote_SUITE.erl @@ -26,7 +26,8 @@ -compile(export_all). suite() -> - [{ct_hooks, [{cth_conn_log,[{ct_netconfc,[{log_type,html}]}]}]}]. + [{timetrap,?default_timeout}, + {ct_hooks, [{cth_conn_log,[{ct_netconfc,[{log_type,html}]}]}]}]. all() -> case os:find_executable("ssh") of @@ -48,13 +49,10 @@ end_per_group(_GroupName, Config) -> init_per_testcase(Case, Config) -> stop_node(Case), - Dog = test_server:timetrap(?default_timeout), - [{watchdog, Dog}|Config]. + Config. end_per_testcase(Case, Config) -> stop_node(Case), - Dog=?config(watchdog, Config), - test_server:timetrap_cancel(Dog), ok. stop_node(Case) -> @@ -63,14 +61,19 @@ stop_node(Case) -> rpc:call(Node,erlang,halt,[]). +init_per_suite() -> + [{timetrap,2*?default_timeout}]. % making dsa files can be slow init_per_suite(Config) -> - case {crypto:start(),ssh:start()} of - {ok,ok} -> + case ssh:start() of + Ok when Ok==ok; Ok=={error,{already_started,ssh}} -> + ct:log("SSH started locally",[]), {ok, _} = netconfc_test_lib:get_id_keys(Config), netconfc_test_lib:make_dsa_files(Config), + ct:log("dsa files created",[]), Config; - _ -> - {skip, "Crypto and/or SSH could not be started locally!"} + Other -> + ct:log("could not start ssh locally: ~p",[Other]), + {skip, "SSH could not be started locally!"} end. end_per_suite(Config) -> @@ -87,12 +90,15 @@ remote_crash(Config) -> Pa = filename:dirname(code:which(?NS)), true = rpc:call(Node,code,add_patha,[Pa]), - case {rpc:call(Node,crypto,start,[]),rpc:call(Node,ssh,start,[])} of - {ok,ok} -> + case rpc:call(Node,ssh,start,[]) of + Ok when Ok==ok; Ok=={error,{already_started,ssh}} -> + ct:log("SSH started remote",[]), Server = rpc:call(Node,?NS,start,[?config(data_dir,Config)]), + ct:log("netconf server started remote",[]), remote_crash(Node,Config); - _ -> - {skip, "Crypto and/or SSH could not be started remote!"} + Other -> + ct:log("could not start ssh remote: ~p",[Other]), + {skip, "SSH could not be started remote!"} end. remote_crash(Node,Config) -> diff --git a/lib/dialyzer/README b/lib/dialyzer/README index 82d0f5ec48..951a92469b 100644 --- a/lib/dialyzer/README +++ b/lib/dialyzer/README @@ -6,7 +6,7 @@ ## Copyright: Held by the authors; all rights reserved (2004 - 2010). ##---------------------------------------------------------------------------- -The DIALYZER, a DIscrepany AnaLYZer for ERlang programs. +The DIALYZER, a DIscrepancy AnaLYZer for ERlang programs. ----------------------------------------------- diff --git a/lib/dialyzer/doc/about.txt b/lib/dialyzer/doc/about.txt index 7d9d819731..1318d9a65e 100644 --- a/lib/dialyzer/doc/about.txt +++ b/lib/dialyzer/doc/about.txt @@ -1,5 +1,5 @@ This is DIALYZER version 2.1.0 - DIALYZER is a DIscrepany AnaLYZer for ERlang programs. + DIALYZER is a DIscrepancy AnaLYZer for ERlang programs. Copyright (C) Tobias Lindahl <[email protected]> Kostis Sagonas <[email protected]> diff --git a/lib/dialyzer/doc/manual.txt b/lib/dialyzer/doc/manual.txt index 29c9518d84..be1fd2f8bc 100644 --- a/lib/dialyzer/doc/manual.txt +++ b/lib/dialyzer/doc/manual.txt @@ -4,7 +4,7 @@ ## Kostis Sagonas <[email protected]> ##---------------------------------------------------------------------------- -The DIALYZER, a DIscrepany AnaLYZer for ERlang programs. +The DIALYZER, a DIscrepancy AnaLYZer for ERlang programs. ----------------------------------------------- diff --git a/lib/dialyzer/info b/lib/dialyzer/info index 9fba4b54ad..b9ea26b712 100644 --- a/lib/dialyzer/info +++ b/lib/dialyzer/info @@ -1,2 +1,2 @@ group: tools -short: The DIALYZER, a DIscrepany AnaLYZer for ERlang programs. +short: The DIALYZER, a DIscrepancy AnaLYZer for ERlang programs. diff --git a/lib/dialyzer/src/dialyzer_gui_wx.erl b/lib/dialyzer/src/dialyzer_gui_wx.erl index 9f344d87ff..30d2bdeca4 100644 --- a/lib/dialyzer/src/dialyzer_gui_wx.erl +++ b/lib/dialyzer/src/dialyzer_gui_wx.erl @@ -422,7 +422,7 @@ gui_loop(#gui_state{backend_pid = BackendPid, doc_plt = DocPlt, #wx{id=?menuID_HELP_ABOUT, obj=Frame, event=#wxCommand{type=command_menu_selected}} -> Message = " This is DIALYZER version " ++ ?VSN ++ " \n"++ - "DIALYZER is a DIscrepany AnaLYZer for ERlang programs.\n\n"++ + "DIALYZER is a DIscrepancy AnaLYZer for ERlang programs.\n\n"++ " Copyright (C) Tobias Lindahl <[email protected]>\n"++ " Kostis Sagonas <[email protected]>\n\n", output_sms(State, "About Dialyzer", Message, info), diff --git a/lib/kernel/src/dist_util.erl b/lib/kernel/src/dist_util.erl index 580a896357..47d0c1b861 100644 --- a/lib/kernel/src/dist_util.erl +++ b/lib/kernel/src/dist_util.erl @@ -156,7 +156,7 @@ is_allowed(#hs_data{other_node = Node, send_status(HSData, not_allowed), error_msg("** Connection attempt from " "disallowed node ~w ** ~n", [Node]), - ?shutdown(Node); + ?shutdown2(Node, {is_allowed, not_allowed}); _ -> true end. @@ -607,10 +607,10 @@ recv_challenge_reply(#hs_data{socket = Socket, _ -> error_msg("** Connection attempt from " "disallowed node ~w ** ~n", [NodeB]), - ?shutdown(NodeB) + ?shutdown2(NodeB, {recv_challenge_reply_failed, bad_cookie}) end; - _ -> - ?shutdown(no_node) + Other -> + ?shutdown2(no_node, {recv_challenge_reply_failed, Other}) end. recv_challenge_ack(#hs_data{socket = Socket, f_recv = FRecv, diff --git a/lib/kernel/src/rpc.erl b/lib/kernel/src/rpc.erl index 6f9ce17c0c..21bff02214 100644 --- a/lib/kernel/src/rpc.erl +++ b/lib/kernel/src/rpc.erl @@ -63,7 +63,7 @@ %%------------------------------------------------------------------------ --type state() :: gb_trees:tree(pid(), {pid(), reference()}). +-type state() :: map(). %%------------------------------------------------------------------------ @@ -91,7 +91,7 @@ stop(Rpc) -> init([]) -> process_flag(trap_exit, true), - {ok, gb_trees:empty()}. + {ok, maps:new()}. -spec handle_call(term(), term(), state()) -> {'noreply', state()} | @@ -130,29 +130,15 @@ handle_cast(_, S) -> -spec handle_info(term(), state()) -> {'noreply', state()}. +handle_info({'DOWN', _, process, Caller, normal}, S) -> + {noreply, maps:remove(Caller, S)}; handle_info({'DOWN', _, process, Caller, Reason}, S) -> - case gb_trees:lookup(Caller, S) of - {value, To} -> - receive - {Caller, {reply, Reply}} -> - gen_server:reply(To, Reply) - after 0 -> - gen_server:reply(To, {badrpc, {'EXIT', Reason}}) - end, - {noreply, gb_trees:delete(Caller, S)}; - none -> - {noreply, S} - end; -handle_info({Caller, {reply, Reply}}, S) -> - case gb_trees:lookup(Caller, S) of - {value, To} -> - receive - {'DOWN', _, process, Caller, _} -> - gen_server:reply(To, Reply), - {noreply, gb_trees:delete(Caller, S)} - end; - none -> - {noreply, S} + case maps:get(Caller, S, undefined) of + undefined -> + {noreply, S}; + {_, _} = To -> + gen_server:reply(To, {badrpc, {'EXIT', Reason}}), + {noreply, maps:remove(Caller, S)} end; handle_info({From, {sbcast, Name, Msg}}, S) -> _ = case catch Name ! Msg of %% use catch to get the printout @@ -190,7 +176,6 @@ code_change(_, S, _) -> %% Auxiliary function to avoid a false dialyzer warning -- do not inline %% handle_call_call(Mod, Fun, Args, Gleader, To, S) -> - RpcServer = self(), %% Spawn not to block the rpc server. {Caller,_} = erlang:spawn_monitor( @@ -205,9 +190,9 @@ handle_call_call(Mod, Fun, Args, Gleader, To, S) -> Result -> Result end, - RpcServer ! {self(), {reply, Reply}} + gen_server:reply(To, Reply) end), - {noreply, gb_trees:insert(Caller, To, S)}. + {noreply, maps:put(Caller, To, S)}. %% RPC aid functions .... diff --git a/lib/kernel/test/erl_distribution_SUITE.erl b/lib/kernel/test/erl_distribution_SUITE.erl index bf1548591a..eb58e92224 100644 --- a/lib/kernel/test/erl_distribution_SUITE.erl +++ b/lib/kernel/test/erl_distribution_SUITE.erl @@ -634,7 +634,7 @@ monitor_nodes_nodedown_reason(Config) when is_list(Config) -> stop_node(N4), true = net_kernel:disconnect(N2), TickTime = net_kernel:get_net_ticktime(), - SleepTime = TickTime + (TickTime div 4), + SleepTime = TickTime + (TickTime div 2), spawn(N3, fun () -> block_emu(SleepTime*1000), halt() @@ -911,15 +911,14 @@ monitor_nodes_otp_6481_test(Config, TestType) when is_list(Config) -> %% Verify that '{nodeup, Node}' comes before '{NodeMsg, 1}' (the message %% bringing up the connection). - no_msgs(500), {nodeup, Node} = receive Msg1 -> Msg1 end, - {NodeMsg, 1} = receive Msg2 -> Msg2 end, + {NodeMsg, N} = receive Msg2 -> Msg2 end, %% msg stream has begun, kill the node RemotePid ! {self(), kill_it}, %% Verify that '{nodedown, Node}' comes after the last '{NodeMsg, N}' %% message. - {nodedown, Node} = flush_node_msgs(NodeMsg, 2), + {nodedown, Node} = flush_node_msgs(NodeMsg, N+1), no_msgs(500), Mon = erlang:monitor(process, MN), @@ -932,8 +931,10 @@ monitor_nodes_otp_6481_test(Config, TestType) when is_list(Config) -> flush_node_msgs(NodeMsg, No) -> case receive Msg -> Msg end of - {NodeMsg, No} -> flush_node_msgs(NodeMsg, No+1); - OtherMsg -> OtherMsg + {NodeMsg, N} when N >= No -> + flush_node_msgs(NodeMsg, N+1); + OtherMsg -> + OtherMsg end. node_loop_send(Pid, Msg, No) -> diff --git a/lib/kernel/test/seq_trace_SUITE.erl b/lib/kernel/test/seq_trace_SUITE.erl index 000994751f..be23a1933f 100644 --- a/lib/kernel/test/seq_trace_SUITE.erl +++ b/lib/kernel/test/seq_trace_SUITE.erl @@ -498,7 +498,13 @@ match_set_seq_token(Config) when is_list(Config) -> exit(P2, timeout), {error, "Test node hung"} end, - ok = check_match_set_seq_token_log(Lbl, Log), + + %% Sort the log on Pid, as events from different processes + %% are not guaranteed to arrive in a certain order to the + %% tracer + SortedLog = lists:keysort(2, Log), + + ok = check_match_set_seq_token_log(Lbl, SortedLog), %% stop_node(Sandbox), ok. @@ -551,13 +557,13 @@ do_match_set_seq_token(Label) -> check_match_set_seq_token_log( Label, - [{trace,C,call,{?MODULE,countdown,[B,Ref]}, {0,Label,0,C,0}}, + [{trace,B,call,{?MODULE,bounce, [Ref]}, {0,Label,2,B,1}}, + {trace,B,call,{?MODULE,bounce, [Ref]}, {0,Label,4,B,3}}, + {trace,B,call,{?MODULE,bounce, [Ref]}, {0,Label,6,B,5}}, + {trace,C,call,{?MODULE,countdown,[B,Ref]}, {0,Label,0,C,0}}, {trace,C,call,{?MODULE,countdown,[B,Ref,3]},{0,Label,0,C,0}}, - {trace,B,call,{?MODULE,bounce, [Ref]}, {0,Label,2,B,1}}, {trace,C,call,{?MODULE,countdown,[B,Ref,2]},{0,Label,2,B,1}}, - {trace,B,call,{?MODULE,bounce, [Ref]}, {0,Label,4,B,3}}, {trace,C,call,{?MODULE,countdown,[B,Ref,1]},{0,Label,4,B,3}}, - {trace,B,call,{?MODULE,bounce, [Ref]}, {0,Label,6,B,5}}, {trace,C,call,{?MODULE,countdown,[B,Ref,0]},{0,Label,6,B,5}} ]) -> ok; diff --git a/lib/observer/test/crashdump_viewer_SUITE.erl b/lib/observer/test/crashdump_viewer_SUITE.erl index a795c4fe25..73ed890802 100644 --- a/lib/observer/test/crashdump_viewer_SUITE.erl +++ b/lib/observer/test/crashdump_viewer_SUITE.erl @@ -101,7 +101,7 @@ end_per_group(_GroupName, Config) -> init_per_suite(Config) when is_list(Config) -> delete_saved(Config), DataDir = ?config(data_dir,Config), - Rels = [R || R <- [r16b,'17'], ?t:is_release_available(R)] ++ [current], + Rels = [R || R <- ['17','18'], ?t:is_release_available(R)] ++ [current], io:format("Creating crash dumps for the following releases: ~p", [Rels]), AllDumps = create_dumps(DataDir,Rels), [{dumps,AllDumps}|Config]. @@ -606,21 +606,21 @@ dos_dump(DataDir,Rel,Dump) -> rel_opt(Rel) -> case Rel of - r16b -> [{erl,[{release,"r16b_latest"}]}]; '17' -> [{erl,[{release,"17_latest"}]}]; + '18' -> [{erl,[{release,"18_latest"}]}]; current -> [] end. dump_prefix(Rel) -> case Rel of - r16b -> "r16b_dump."; '17' -> "r17_dump."; - current -> "r18_dump." + '18' -> "r18_dump."; + current -> "r19_dump." end. compat_rel(Rel) -> case Rel of - r16b -> "+R16 "; '17' -> "+R17 "; + '18' -> "+R18 "; current -> "" end. diff --git a/lib/runtime_tools/doc/src/LTTng.xml b/lib/runtime_tools/doc/src/LTTng.xml index eab1848e88..4a87133c57 100644 --- a/lib/runtime_tools/doc/src/LTTng.xml +++ b/lib/runtime_tools/doc/src/LTTng.xml @@ -240,6 +240,222 @@ $ make </code> </section> <section> + <title>BEAM Tracepoints</title> + <p>All tracepoints are in the domain of <c>com_ericsson_otp</c></p> + <p>All Erlang types are the string equivalent in LTTng.</p> + + <p><em>scheduler_poll</em></p> + <list type="bulleted"> + <item><c>scheduler : integer</c> :: Scheduler ID. Ex. <c>1</c></item> + <item><c>runnable : integer</c> :: Runnable. Ex. <c>1</c></item> + </list> + <p>Example:</p> + <p><code type="none">scheduler_poll: { cpu_id = 4 }, { scheduler = 1, runnable = 1 }</code></p> + + <p><em>driver_init</em></p> + <list type="bulleted"> + <item><c>driver : string</c> :: Driver name. Ex. <c>"efile"</c></item> + <item><c>major : integer</c> :: Major version. Ex. <c>3</c></item> + <item><c>minor : integer</c> :: Minor version. Ex. <c>1</c></item> + <item><c>flags : integer</c> :: Flags. Ex. <c>1</c></item> + </list> + <p>Example:</p> + <p><code type="none">driver_init: { cpu_id = 2 }, { driver = "caller_drv", major = 3, minor = 3, flags = 1 }</code></p> + + <p><em>driver_start</em></p> + <list type="bulleted"> + <item><c>pid : string</c> :: Process ID. Ex. <c>"<0.131.0>"</c></item> + <item><c>driver : string</c> :: Driver name. Ex. <c>"efile"</c></item> + <item><c>port : string</c> :: Port ID. Ex. <c>"#Port<0.1031>"</c></item> + </list> + <p>Example:</p> + <p><code type="none">driver_start: { cpu_id = 2 }, { pid = "<0.198.0>", driver = "caller_drv", port = "#Port<0.3676>" }</code></p> + + <p><em>driver_output</em></p> + <list type="bulleted"> + <item><c>pid : string</c> :: Process ID. Ex. <c>"<0.131.0>"</c></item> + <item><c>port : string</c> :: Port ID. Ex. <c>"#Port<0.1031>"</c></item> + <item><c>driver : string</c> :: Driver name. Ex. <c>"efile"</c></item> + <item><c>bytes : integer</c> :: Size of data returned. Ex. <c>82</c></item> + </list> + <p>Example:</p> + <p><code type="none">driver_output: { cpu_id = 2 }, { pid = "<0.198.0>", port = "#Port<0.3677>", driver = "/bin/sh -s unix:cmd", bytes = 36 }</code></p> + + <p><em>driver_outputv</em></p> + <list type="bulleted"> + <item><c>pid : string</c> :: Process ID. Ex. <c>"<0.131.0>"</c></item> + <item><c>port : string</c> :: Port ID. Ex. <c>"#Port<0.1031>"</c></item> + <item><c>driver : string</c> :: Driver name. Ex. <c>"efile"</c></item> + <item><c>bytes : integer</c> :: Size of data returned. Ex. <c>82</c></item> + </list> + <p>Example:</p> + <p><code type="none">driver_outputv: { cpu_id = 5 }, { pid = "<0.194.0>", port = "#Port<0.3663>", driver = "tcp_inet", bytes = 3 }</code></p> + + <p><em>driver_ready_input</em></p> + <list type="bulleted"> + <item><c>pid : string</c> :: Process ID. Ex. <c>"<0.131.0>"</c></item> + <item><c>port : string</c> :: Port ID. Ex. <c>"#Port<0.1031>"</c></item> + <item><c>driver : string</c> :: Driver name. Ex. <c>"efile"</c></item> + </list> + <p>Example:</p> + <p><code type="none">driver_ready_input: { cpu_id = 5 }, { pid = "<0.189.0>", port = "#Port<0.3637>", driver = "inet_gethost 4 " }</code></p> + + <p><em>driver_ready_output</em></p> + <list type="bulleted"> + <item><c>pid : string</c> :: Process ID. Ex. <c>"<0.131.0>"</c></item> + <item><c>port : string</c> :: Port ID. Ex. <c>"#Port<0.1031>"</c></item> + <item><c>driver : string</c> :: Driver name. Ex. <c>"efile"</c></item> + </list> + <p>Example:</p> + <p><code type="none">driver_ready_output: { cpu_id = 5 }, { pid = "<0.194.0>", port = "#Port<0.3663>", driver = "tcp_inet" }</code></p> + + <p><em>driver_timeout</em></p> + <list type="bulleted"> + <item><c>pid : string</c> :: Process ID. Ex. <c>"<0.131.0>"</c></item> + <item><c>port : string</c> :: Port ID. Ex. <c>"#Port<0.1031>"</c></item> + <item><c>driver : string</c> :: Driver name. Ex. <c>"efile"</c></item> + </list> + <p>Example:</p> + <p><code type="none">driver_timeout: { cpu_id = 5 }, { pid = "<0.196.0>", port = "#Port<0.3664>", driver = "tcp_inet" }</code></p> + + <p><em>driver_stop_select</em></p> + <list type="bulleted"> + <item><c>driver : string</c> :: Driver name. Ex. <c>"efile"</c></item> + </list> + <p>Example:</p> + <p><code type="none">driver_stop_select: { cpu_id = 5 }, { driver = "unknown" }</code></p> + + <p><em>driver_flush</em></p> + <list type="bulleted"> + <item><c>pid : string</c> :: Process ID. Ex. <c>"<0.131.0>"</c></item> + <item><c>port : string</c> :: Port ID. Ex. <c>"#Port<0.1031>"</c></item> + <item><c>driver : string</c> :: Driver name. Ex. <c>"efile"</c></item> + </list> + <p>Example:</p> + <p><code type="none">driver_flush: { cpu_id = 7 }, { pid = "<0.204.0>", port = "#Port<0.3686>", driver = "tcp_inet" }</code></p> + + <p><em>driver_stop</em></p> + <list type="bulleted"> + <item><c>pid : string</c> :: Process ID. Ex. <c>"<0.131.0>"</c></item> + <item><c>port : string</c> :: Port ID. Ex. <c>"#Port<0.1031>"</c></item> + <item><c>driver : string</c> :: Driver name. Ex. <c>"efile"</c></item> + </list> + <p>Example:</p> + <p><code type="none">driver_stop: { cpu_id = 5 }, { pid = "[]", port = "#Port<0.3673>", driver = "efile" }</code></p> + + <p><em>driver_process_exit</em></p> + <list type="bulleted"> + <item><c>pid : string</c> :: Process ID. Ex. <c>"<0.131.0>"</c></item> + <item><c>port : string</c> :: Port ID. Ex. <c>"#Port<0.1031>"</c></item> + <item><c>driver : string</c> :: Driver name. Ex. <c>"efile"</c></item> + </list> + + <p><em>driver_ready_async</em></p> + <list type="bulleted"> + <item><c>pid : string</c> :: Process ID. Ex. <c>"<0.131.0>"</c></item> + <item><c>port : string</c> :: Port ID. Ex. <c>"#Port<0.1031>"</c></item> + <item><c>driver : string</c> :: Driver name. Ex. <c>"efile"</c></item> + </list> + <p>Example:</p> + <p><code type="none">driver_ready_async: { cpu_id = 3 }, { pid = "<0.181.0>", port = "#Port<0.3622>", driver = "efile" }</code></p> + + <p><em>driver_call</em></p> + <list type="bulleted"> + <item><c>pid : string</c> :: Process ID. Ex. <c>"<0.131.0>"</c></item> + <item><c>port : string</c> :: Port ID. Ex. <c>"#Port<0.1031>"</c></item> + <item><c>driver : string</c> :: Driver name. Ex. <c>"efile"</c></item> + <item><c>command : integer</c> :: Command integer. Ex. <c>1</c></item> + <item><c>bytes : integer</c> :: Size of data returned. Ex. <c>82</c></item> + </list> + <p>Example:</p> + <p><code type="none">driver_call: { cpu_id = 2 }, { pid = "<0.202.0>", port = "#Port<0.3676>", driver = "caller_drv", command = 0, bytes = 2 }</code></p> + + <p><em>driver_control</em></p> + <list type="bulleted"> + <item><c>pid : string</c> :: Process ID. Ex. <c>"<0.131.0>"</c></item> + <item><c>port : string</c> :: Port ID. Ex. <c>"#Port<0.1031>"</c></item> + <item><c>driver : string</c> :: Driver name. Ex. <c>"efile"</c></item> + <item><c>command : integer</c> :: Command integer. Ex. <c>1</c></item> + <item><c>bytes : integer</c> :: Size of data returned. Ex. <c>82</c></item> + </list> + <p>Example:</p> + <p><code type="none">driver_control: { cpu_id = 3 }, { pid = "<0.32767.8191>", port = "#Port<0.0>", driver = "forker", command = 83, bytes = 32 }</code></p> + + <p><em>aio_pool_get</em></p> + <list type="bulleted"> + <item><c>port : string</c> :: Port ID. Ex. <c>"#Port<0.1031>"</c></item> + <item><c>length : integer</c> :: Async queue length. Ex. <c>0</c></item> + </list> + <p>Example:</p> + <p><code type="none">aio_pool_get: { cpu_id = 4 }, { port = "#Port<0.3614>", length = 0 }</code></p> + + <p><em>aio_pool_put</em></p> + <list type="bulleted"> + <item><c>port : string</c> :: Port ID. Ex. <c>"#Port<0.1031>"</c></item> + <item><c>length : integer</c> :: Async queue length. Ex. <c>-1</c></item> + </list> + <p>Async queue length is not defined for <c>put</c> operations.</p> + <p>Example:</p> + <p><code type="none">aio_pool_put: { cpu_id = 3 }, { port = "#Port<0.3614>", length = -1 }</code></p> + + <p><em>carrier_create</em></p> + <list type="bulleted"> + <item><c>type : string</c> :: Carrier type. Ex. <c>"ets_alloc"</c></item> + <item><c>instance : integer</c> :: Allocator instance. Ex. <c>1</c></item> + <item><c>size : integer</c> :: Carrier size. Ex. <c>262144</c></item> + <item><c>mbc_carriers : integer</c> :: Number of multiblock carriers in instance. Ex. <c>3</c></item> + <item><c>mbc_carriers_size : integer</c> :: Total size of multiblock blocks carriers in instance. Ex. <c>1343488</c></item> + <item><c>mbc_blocks : integer</c> :: Number of multiblock blocks in instance. Ex. <c>122</c></item> + <item><c>mbc_blocks_size : integer</c> :: Total size of all multiblock blocks in instance. Ex. <c>285296</c></item> + <item><c>sbc_carriers : integer</c> :: Number of singleblock carriers in instance. Ex. <c>1</c></item> + <item><c>sbc_carriers_size : integer</c> :: Total size of singleblock blocks carriers in instance. Ex. <c>1343488</c></item> + <item><c>sbc_blocks : integer</c> :: Number of singleblocks in instance. Ex. <c>1</c></item> + <item><c>sbc_blocks_size : integer</c> :: Total size of all singleblock blocks in instance. Ex. <c>285296</c></item> + + </list> + <p>Example:</p> + <p><code type="none">carrier_create: { cpu_id = 2 }, { type = "ets_alloc", instance = 7, size = 2097152, mbc_carriers = 4, mbc_carriers_size = 3440640, mbc_blocks = 526, mbc_blocks_size = 1278576, sbc_carriers = 0, sbc_carriers_size = 0, sbc_blocks = 0, sbc_blocks_size = 0 }</code></p> + + <p><em>carrier_destroy</em></p> + <list type="bulleted"> + <item><c>type : string</c> :: Carrier type. Ex. <c>"ets_alloc"</c></item> + <item><c>instance : integer</c> :: Allocator instance. Ex. <c>1</c></item> + <item><c>size : integer</c> :: Carrier size. Ex. <c>262144</c></item> + <item><c>mbc_carriers : integer</c> :: Number of multiblock carriers in instance. Ex. <c>3</c></item> + <item><c>mbc_carriers_size : integer</c> :: Total size of multiblock blocks carriers in instance. Ex. <c>1343488</c></item> + <item><c>mbc_blocks : integer</c> :: Number of multiblock blocks in instance. Ex. <c>122</c></item> + <item><c>mbc_blocks_size : integer</c> :: Total size of all multiblock blocks in instance. Ex. <c>285296</c></item> + <item><c>sbc_carriers : integer</c> :: Number of singleblock carriers in instance. Ex. <c>1</c></item> + <item><c>sbc_carriers_size : integer</c> :: Total size of singleblock blocks carriers in instance. Ex. <c>1343488</c></item> + <item><c>sbc_blocks : integer</c> :: Number of singleblocks in instance. Ex. <c>1</c></item> + <item><c>sbc_blocks_size : integer</c> :: Total size of all singleblock blocks in instance. Ex. <c>285296</c></item> + + </list> + <p>Example:</p> + <p><code type="none">carrier_destroy: { cpu_id = 6 }, { type = "ets_alloc", instance = 7, size = 262144, mbc_carriers = 3, mbc_carriers_size = 3178496, mbc_blocks = 925, mbc_blocks_size = 2305336, sbc_carriers = 0, sbc_carriers_size = 0, sbc_blocks = 0, sbc_blocks_size = 0 }</code></p> + + <p><em>carrier_pool_put</em></p> + <list type="bulleted"> + <item><c>type : string</c> :: Carrier type. Ex. <c>"ets_alloc"</c></item> + <item><c>instance : integer</c> :: Allocator instance. Ex. <c>1</c></item> + <item><c>size : integer</c> :: Carrier size. Ex. <c>262144</c></item> + </list> + <p>Example:</p> + <p><code type="none">carrier_pool_put: { cpu_id = 3 }, { type = "ets_alloc", instance = 5, size = 1048576 }</code></p> + + <p><em>carrier_pool_get</em></p> + <list type="bulleted"> + <item><c>type : string</c> :: Carrier type. Ex. <c>"ets_alloc"</c></item> + <item><c>instance : integer</c> :: Allocator instance. Ex. <c>1</c></item> + <item><c>size : integer</c> :: Carrier size. Ex. <c>262144</c></item> + </list> + <p>Example:</p> + <p><code type="none">carrier_pool_get: { cpu_id = 7 }, { type = "ets_alloc", instance = 4, size = 3208 }</code></p> + + </section> + + + <section> <title>Examples</title> </section> </chapter> diff --git a/lib/runtime_tools/src/system_information.erl b/lib/runtime_tools/src/system_information.erl index ad7ee7311c..1add01612d 100644 --- a/lib/runtime_tools/src/system_information.erl +++ b/lib/runtime_tools/src/system_information.erl @@ -28,31 +28,25 @@ -behaviour(gen_server). %% API --export([ - report/0, +-export([report/0, from_file/1, - to_file/1 - ]). --export([ - start/0, stop/0, - load_report/0, load_report/2, - applications/0, applications/1, - application/1, application/2, - environment/0, environment/1, - module/1, module/2, - modules/1, - sanity_check/0 - ]). + to_file/1]). +-export([start/0, stop/0, + load_report/0, load_report/2, + applications/0, applications/1, + application/1, application/2, + environment/0, environment/1, + module/1, module/2, + modules/1, + sanity_check/0]). %% gen_server callbacks --export([ - init/1, - handle_call/3, - handle_cast/2, - handle_info/2, - terminate/2, - code_change/3 - ]). +-export([init/1, + handle_call/3, + handle_cast/2, + handle_info/2, + terminate/2, + code_change/3]). -define(SERVER, ?MODULE). @@ -71,13 +65,13 @@ start() -> gen_server:start({local, ?SERVER}, ?MODULE, [], []). stop() -> - gen_server:call(?SERVER, stop). + gen_server:call(?SERVER, stop, infinity). load_report() -> load_report(data, report()). load_report(file, File) -> load_report(data, from_file(File)); load_report(data, Report) -> - start(), gen_server:call(?SERVER, {load_report, Report}). + start(), gen_server:call(?SERVER, {load_report, Report}, infinity). report() -> [ {init_arguments, init:get_arguments()}, @@ -120,22 +114,22 @@ from_file(File) -> applications() -> applications([]). applications(Opts) when is_list(Opts) -> - gen_server:call(?SERVER, {applications, Opts}). + gen_server:call(?SERVER, {applications, Opts}, infinity). application(App) when is_atom(App) -> application(App, []). application(App, Opts) when is_atom(App), is_list(Opts) -> - gen_server:call(?SERVER, {application, App, Opts}). + gen_server:call(?SERVER, {application, App, Opts}, infinity). environment() -> environment([]). environment(Opts) when is_list(Opts) -> - gen_server:call(?SERVER, {environment, Opts}). + gen_server:call(?SERVER, {environment, Opts}, infinity). module(M) when is_atom(M) -> module(M, []). module(M, Opts) when is_atom(M), is_list(Opts) -> - gen_server:call(?SERVER, {module, M, Opts}). + gen_server:call(?SERVER, {module, M, Opts}, infinity). modules(Opt) when is_atom(Opt) -> - gen_server:call(?SERVER, {modules, Opt}). + gen_server:call(?SERVER, {modules, Opt}, infinity). -spec sanity_check() -> ok | {failed, Failures} when diff --git a/lib/runtime_tools/test/dbg_SUITE.erl b/lib/runtime_tools/test/dbg_SUITE.erl index 9c9d6ca352..0777503ef7 100644 --- a/lib/runtime_tools/test/dbg_SUITE.erl +++ b/lib/runtime_tools/test/dbg_SUITE.erl @@ -167,8 +167,8 @@ distributed(Config) when is_list(Config) -> {value, {matched, Node, 1}} = lists:keysearch(Node, 2, Z), dbg:cn(Node), dbg:tp(dbg,ln,[]), - ok = rpc:call(Node, dbg, ltp, []), - ok = rpc:call(Node, dbg, ln, []), + ok = rpc:block_call(Node, dbg, ltp, []), + ok = rpc:block_call(Node, dbg, ln, []), ok = dbg:ln(), S = self(), {TraceSend, TraceCall} = @@ -447,12 +447,6 @@ file_port_schedfix1(Config) when is_list(Config) -> %% {ok,[{matched,_,_}]} = dbg:p(all, [clear]), stop(), - % Some debug code to run on all platforms, for finding the fault on genny - % Dont touch please /PaN - io:format("Trace dump by PaN BEGIN~n"), - dbg:trace_client(file,{FName, wrap, ".wraplog"},{fun(end_of_trace,Pid)-> Pid ! done; (Mesg,Pid) -> io:format("~w~n",[Mesg]),Pid end,self()}), - receive done -> ok end, - io:format("Trace dump by PaN END~n"), %% %% Get the trace result %% @@ -473,14 +467,12 @@ file_port_schedfix1(Config) when is_list(Config) -> %% %% Analyze the result %% - {Min, Max} = - lists:foldl( - fun({_Pid, M}, {Mi, Ma}) -> - {if M < Mi -> M; true -> Mi end, - if M > Ma -> M; true -> Ma end} - end, - {void, 0}, - Result), + {Min, Max} = lists:foldl(fun({_Pid, M}, {Mi, Ma}) -> + {if M < Mi -> M; true -> Mi end, + if M > Ma -> M; true -> Ma end} + end, + {void, 0}, + Result), % More PaN debug io:format("Min = ~f, Max = ~f~n",[Min,Max]), %% @@ -895,6 +887,10 @@ schedstat_handler(TraceMsg, {Parent, Tag, Data} = State) -> Data end, {Parent, Tag, NewData}; + {trace_ts,_Pid,spawned,_OtherPid,_,_Ts} -> + State; + {trace_ts,_Pid,getting_linked,_OtherPid,_Ts} -> + State; {trace_ts, Pid, exit, normal, {A3, B3, C3}} -> NewData = case lists:keysearch(Pid, 1, Data) of diff --git a/lib/ssh/test/ssh_sup_SUITE.erl b/lib/ssh/test/ssh_sup_SUITE.erl index 2dc4263603..f8929b30ff 100644 --- a/lib/ssh/test/ssh_sup_SUITE.erl +++ b/lib/ssh/test/ssh_sup_SUITE.erl @@ -108,18 +108,19 @@ sshc_subtree(Config) when is_list(Config) -> {ok, Pid1} = ssh:connect(Host, Port, [{silently_accept_hosts, true}, {user_interaction, false}, {user, ?USER}, {password, ?PASSWD},{user_dir, UserDir}]), - ?wait_match([{_, _,supervisor,[ssh_connection_handler]}], + + ?wait_match([{_, _,worker,[ssh_connection_handler]}], supervisor:which_children(sshc_sup)), {ok, Pid2} = ssh:connect(Host, Port, [{silently_accept_hosts, true}, {user_interaction, false}, {user, ?USER}, {password, ?PASSWD}, {user_dir, UserDir}]), - ?wait_match([{_,_,supervisor,[ssh_connection_handler]}, - {_,_,supervisor,[ssh_connection_handler]}], + ?wait_match([{_,_,worker,[ssh_connection_handler]}, + {_,_,worker,[ssh_connection_handler]}], supervisor:which_children(sshc_sup)), ssh:close(Pid1), - ?wait_match([{_,_,supervisor,[ssh_connection_handler]}], + ?wait_match([{_,_,worker,[ssh_connection_handler]}], supervisor:which_children(sshc_sup)), ssh:close(Pid2), ?wait_match([], supervisor:which_children(sshc_sup)). diff --git a/lib/ssl/test/ssl_certificate_verify_SUITE.erl b/lib/ssl/test/ssl_certificate_verify_SUITE.erl index 1ce6f3b567..49c0b9c5a1 100644 --- a/lib/ssl/test/ssl_certificate_verify_SUITE.erl +++ b/lib/ssl/test/ssl_certificate_verify_SUITE.erl @@ -52,8 +52,8 @@ groups() -> {error_handling, [],error_handling_tests()}]. tests() -> - [server_verify_peer, - server_verify_none, + [verify_peer, + verify_none, server_require_peer_cert_ok, server_require_peer_cert_fail, server_require_peer_cert_partial_chain, @@ -133,9 +133,9 @@ end_per_testcase(_TestCase, Config) -> %% Test Cases -------------------------------------------------------- %%-------------------------------------------------------------------- -server_verify_peer() -> - [{doc,"Test server option verify_peer"}]. -server_verify_peer(Config) when is_list(Config) -> +verify_peer() -> + [{doc,"Test option verify_peer"}]. +verify_peer(Config) when is_list(Config) -> ClientOpts = ?config(client_verification_opts, Config), ServerOpts = ?config(server_verification_opts, Config), Active = ?config(active, Config), @@ -158,10 +158,10 @@ server_verify_peer(Config) when is_list(Config) -> ssl_test_lib:close(Client). %%-------------------------------------------------------------------- -server_verify_none() -> - [{doc,"Test server option verify_none"}]. +verify_none() -> + [{doc,"Test option verify_none"}]. -server_verify_none(Config) when is_list(Config) -> +verify_none(Config) when is_list(Config) -> ClientOpts = ?config(client_verification_opts, Config), ServerOpts = ?config(server_verification_opts, Config), Active = ?config(active, Config), @@ -231,18 +231,21 @@ server_require_peer_cert_ok(Config) when is_list(Config) -> ServerOpts = [{verify, verify_peer}, {fail_if_no_peer_cert, true} | ?config(server_verification_opts, Config)], ClientOpts = ?config(client_verification_opts, Config), + Active = ?config(active, Config), + ReceiveFunction = ?config(receive_function, Config), {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config), + Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0}, {from, self()}, - {mfa, {ssl_test_lib,send_recv_result, []}}, - {options, [{active, false} | ServerOpts]}]), + {mfa, {ssl_test_lib, ReceiveFunction, []}}, + {options, [{active, Active} | ServerOpts]}]), Port = ssl_test_lib:inet_port(Server), Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port}, {host, Hostname}, {from, self()}, - {mfa, {ssl_test_lib, send_recv_result, []}}, - {options, [{active, false} | ClientOpts]}]), + {mfa, {ssl_test_lib, ReceiveFunction, []}}, + {options, [{active, Active} | ClientOpts]}]), ssl_test_lib:check_result(Server, ok, Client, ok), ssl_test_lib:close(Server), @@ -324,6 +327,8 @@ server_require_peer_cert_allow_partial_chain(Config) when is_list(Config) -> | ?config(server_verification_opts, Config)], ClientOpts = ?config(client_verification_opts, Config), {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config), + Active = ?config(active, Config), + ReceiveFunction = ?config(receive_function, Config), {ok, ServerCAs} = file:read_file(proplists:get_value(cacertfile, ServerOpts)), [{_,_,_}, {_, IntermidiateCA, _}] = public_key:pem_decode(ServerCAs), @@ -339,16 +344,17 @@ server_require_peer_cert_allow_partial_chain(Config) when is_list(Config) -> Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0}, {from, self()}, - {mfa, {ssl_test_lib, send_recv_result_active, []}}, - {options, [{cacerts, [IntermidiateCA]}, + {mfa, {ssl_test_lib, ReceiveFunction, []}}, + {options, [{active, Active}, + {cacerts, [IntermidiateCA]}, {partial_chain, PartialChain} | proplists:delete(cacertfile, ServerOpts)]}]), Port = ssl_test_lib:inet_port(Server), Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port}, {host, Hostname}, {from, self()}, - {mfa, {ssl_test_lib, send_recv_result_active, []}}, - {options, ClientOpts}]), + {mfa, {ssl_test_lib, ReceiveFunction, []}}, + {options, [{active, Active} | ClientOpts]}]), ssl_test_lib:check_result(Server, ok, Client, ok), ssl_test_lib:close(Server), ssl_test_lib:close(Client). @@ -533,32 +539,6 @@ verify_fun_always_run_server(Config) when is_list(Config) -> %%-------------------------------------------------------------------- -client_verify_none_passive() -> - [{doc,"Test client option verify_none"}]. - -client_verify_none_passive(Config) when is_list(Config) -> - ClientOpts = ?config(client_opts, Config), - ServerOpts = ?config(server_opts, Config), - {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config), - Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0}, - {from, self()}, - {mfa, {ssl_test_lib, send_recv_result, []}}, - {options, [{active, false} - | ServerOpts]}]), - Port = ssl_test_lib:inet_port(Server), - - Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port}, - {host, Hostname}, - {from, self()}, - {mfa, {ssl_test_lib, send_recv_result, []}}, - {options, [{active, false}, - {verify, verify_none} - | ClientOpts]}]), - - ssl_test_lib:check_result(Server, ok, Client, ok), - ssl_test_lib:close(Server), - ssl_test_lib:close(Client). -%%-------------------------------------------------------------------- cert_expired() -> [{doc,"Test server with expired certificate"}]. @@ -627,64 +607,6 @@ two_digits_str(N) -> lists:flatten(io_lib:format("~p", [N])). %%-------------------------------------------------------------------- - -client_verify_none_active() -> - [{doc,"Test client option verify_none"}]. - -client_verify_none_active(Config) when is_list(Config) -> - ClientOpts = ?config(client_opts, Config), - ServerOpts = ?config(server_opts, Config), - {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config), - Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0}, - {from, self()}, - {mfa, {ssl_test_lib, - send_recv_result_active, []}}, - {options, [{active, true} - | ServerOpts]}]), - Port = ssl_test_lib:inet_port(Server), - Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port}, - {host, Hostname}, - {from, self()}, - {mfa, {ssl_test_lib, - send_recv_result_active, []}}, - {options, [{active, true}, - {verify, verify_none} - | ClientOpts]}]), - - ssl_test_lib:check_result(Server, ok, Client, ok), - ssl_test_lib:close(Server), - ssl_test_lib:close(Client). - -%%-------------------------------------------------------------------- -client_verify_none_active_once() -> - [{doc,"Test client option verify_none"}]. - -client_verify_none_active_once(Config) when is_list(Config) -> - ClientOpts = ?config(client_opts, Config), - ServerOpts = ?config(server_opts, Config), - - {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config), - Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0}, - {from, self()}, - {mfa, {ssl_test_lib, send_recv_result_active, []}}, - {options, [{active, once} | ServerOpts]}]), - Port = ssl_test_lib:inet_port(Server), - - Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port}, - {host, Hostname}, - {from, self()}, - {mfa, {ssl_test_lib, - send_recv_result_active_once, - []}}, - {options, [{active, once}, - {verify, verify_none} - | ClientOpts]}]), - - ssl_test_lib:check_result(Server, ok, Client, ok), - ssl_test_lib:close(Server), - ssl_test_lib:close(Client). - -%%-------------------------------------------------------------------- extended_key_usage_verify_peer() -> [{doc,"Test cert that has a critical extended_key_usage extension in verify_peer mode"}]. diff --git a/lib/stdlib/src/erl_lint.erl b/lib/stdlib/src/erl_lint.erl index b14102ac38..2508f96b91 100644 --- a/lib/stdlib/src/erl_lint.erl +++ b/lib/stdlib/src/erl_lint.erl @@ -1502,7 +1502,7 @@ pattern({op,_Line,'++',{string,_Li,_S},R}, Vt, Old, Bvt, St) -> pattern({match,_Line,Pat1,Pat2}, Vt, Old, Bvt, St0) -> {Lvt,Bvt1,St1} = pattern(Pat1, Vt, Old, Bvt, St0), {Rvt,Bvt2,St2} = pattern(Pat2, Vt, Old, Bvt, St1), - St3 = reject_bin_alias(Pat1, Pat2, St2), + St3 = reject_invalid_alias(Pat1, Pat2, Vt, St2), {vtmerge_pat(Lvt, Rvt),vtmerge_pat(Bvt1,Bvt2),St3}; %% Catch legal constant expressions, including unary +,-. pattern(Pat, _Vt, _Old, _Bvt, St) -> @@ -1517,56 +1517,77 @@ pattern_list(Ps, Vt, Old, Bvt0, St) -> {vtmerge_pat(Pvt, Psvt),vtmerge_pat(Bvt,Bvt1),St1} end, {[],[],St}, Ps). -%% reject_bin_alias(Pat, Expr, St) -> St' + + +%% reject_invalid_alias(Pat, Expr, Vt, St) -> St' %% Reject aliases for binary patterns at the top level. +%% Reject aliases for maps patterns at the top level. +%% The variables table (Vt) are for maps checkking. + +reject_invalid_alias_expr({bin,_,_}=P, {match,_,P0,E}, Vt, St0) -> + St = reject_invalid_alias(P, P0, Vt, St0), + reject_invalid_alias_expr(P, E, Vt, St); +reject_invalid_alias_expr({map,_,_}=P, {match,_,P0,E}, Vt, St0) -> + St = reject_invalid_alias(P, P0, Vt, St0), + reject_invalid_alias_expr(P, E, Vt, St); +reject_invalid_alias_expr({match,_,_,_}=P, {match,_,P0,E}, Vt, St0) -> + St = reject_invalid_alias(P, P0, Vt, St0), + reject_invalid_alias_expr(P, E, Vt, St); +reject_invalid_alias_expr(_, _, _, St) -> St. -reject_bin_alias_expr({bin,_,_}=P, {match,_,P0,E}, St0) -> - St = reject_bin_alias(P, P0, St0), - reject_bin_alias_expr(P, E, St); -reject_bin_alias_expr({match,_,_,_}=P, {match,_,P0,E}, St0) -> - St = reject_bin_alias(P, P0, St0), - reject_bin_alias_expr(P, E, St); -reject_bin_alias_expr(_, _, St) -> St. -%% reject_bin_alias(Pat1, Pat2, St) -> St' +%% reject_invalid_alias(Pat1, Pat2, St) -> St' %% Aliases of binary patterns, such as <<A:8>> = <<B:4,C:4>> or even %% <<A:8>> = <<A:8>>, are not allowed. Traverse the patterns in parallel %% and generate an error if any binary aliases are found. %% We generate an error even if is obvious that the overall pattern can't %% possibly match, for instance, {a,<<A:8>>,c}={x,<<A:8>>} WILL generate an %% error. +%% Maps should reject unbound variables here. -reject_bin_alias({bin,Line,_}, {bin,_,_}, St) -> +reject_invalid_alias({bin,Line,_}, {bin,_,_}, _, St) -> add_error(Line, illegal_bin_pattern, St); -reject_bin_alias({cons,_,H1,T1}, {cons,_,H2,T2}, St0) -> - St = reject_bin_alias(H1, H2, St0), - reject_bin_alias(T1, T2, St); -reject_bin_alias({tuple,_,Es1}, {tuple,_,Es2}, St) -> - reject_bin_alias_list(Es1, Es2, St); -reject_bin_alias({record,_,Name1,Pfs1}, {record,_,Name2,Pfs2}, +reject_invalid_alias({map,_Line,Ps1}, {map,_,Ps2}, Vt, St0) -> + Fun = fun ({map_field_exact,L,{var,_,K},_V}, Sti) -> + case is_var_bound(K,Vt) of + true -> + Sti; + false -> + add_error(L, {unbound_var,K}, Sti) + end; + ({map_field_exact,_L,_K,_V}, Sti) -> + Sti + end, + foldl(Fun, foldl(Fun, St0, Ps1), Ps2); +reject_invalid_alias({cons,_,H1,T1}, {cons,_,H2,T2}, Vt, St0) -> + St = reject_invalid_alias(H1, H2, Vt, St0), + reject_invalid_alias(T1, T2, Vt, St); +reject_invalid_alias({tuple,_,Es1}, {tuple,_,Es2}, Vt, St) -> + reject_invalid_alias_list(Es1, Es2, Vt, St); +reject_invalid_alias({record,_,Name1,Pfs1}, {record,_,Name2,Pfs2}, Vt, #lint{records=Recs}=St) -> case {dict:find(Name1, Recs),dict:find(Name2, Recs)} of {{ok,{_Line1,Fields1}},{ok,{_Line2,Fields2}}} -> - reject_bin_alias_rec(Pfs1, Pfs2, Fields1, Fields2, St); + reject_invalid_alias_rec(Pfs1, Pfs2, Fields1, Fields2, Vt, St); {_,_} -> %% One or more non-existing records. (An error messages has %% already been generated, so we are done here.) St end; -reject_bin_alias({match,_,P1,P2}, P, St0) -> - St = reject_bin_alias(P1, P, St0), - reject_bin_alias(P2, P, St); -reject_bin_alias(P, {match,_,_,_}=M, St) -> - reject_bin_alias(M, P, St); -reject_bin_alias(_P1, _P2, St) -> St. - -reject_bin_alias_list([E1|Es1], [E2|Es2], St0) -> - St = reject_bin_alias(E1, E2, St0), - reject_bin_alias_list(Es1, Es2, St); -reject_bin_alias_list(_, _, St) -> St. - -reject_bin_alias_rec(PfsA0, PfsB0, FieldsA0, FieldsB0, St) -> +reject_invalid_alias({match,_,P1,P2}, P, Vt, St0) -> + St = reject_invalid_alias(P1, P, Vt, St0), + reject_invalid_alias(P2, P, Vt, St); +reject_invalid_alias(P, {match,_,_,_}=M, Vt, St) -> + reject_invalid_alias(M, P, Vt, St); +reject_invalid_alias(_P1, _P2, _Vt, St) -> St. + +reject_invalid_alias_list([E1|Es1], [E2|Es2], Vt, St0) -> + St = reject_invalid_alias(E1, E2, Vt, St0), + reject_invalid_alias_list(Es1, Es2, Vt, St); +reject_invalid_alias_list(_, _, _, St) -> St. + +reject_invalid_alias_rec(PfsA0, PfsB0, FieldsA0, FieldsB0, Vt, St) -> %% We treat records as if they have been converted to tuples. PfsA1 = rbia_field_vars(PfsA0), PfsB1 = rbia_field_vars(PfsB0), @@ -1582,7 +1603,7 @@ reject_bin_alias_rec(PfsA0, PfsB0, FieldsA0, FieldsB0, St) -> D = sofs:projection({external,fun({_,_,P1,_,P2}) -> {P1,P2} end}, C), E = sofs:to_external(D), {Ps1,Ps2} = lists:unzip(E), - reject_bin_alias_list(Ps1, Ps2, St). + reject_invalid_alias_list(Ps1, Ps2, Vt, St). rbia_field_vars(Fs) -> [{Name,Pat} || {record_field,_,{atom,_,Name},Pat} <- Fs]. @@ -2284,7 +2305,7 @@ expr({'catch',Line,E}, Vt, St0) -> expr({match,_Line,P,E}, Vt, St0) -> {Evt,St1} = expr(E, Vt, St0), {Pvt,Bvt,St2} = pattern(P, vtupdate(Evt, Vt), St1), - St = reject_bin_alias_expr(P, E, St2), + St = reject_invalid_alias_expr(P, E, Vt, St2), {vtupdate(Bvt, vtmerge(Evt, Pvt)),St}; %% No comparison or boolean operators yet. expr({op,_Line,_Op,A}, Vt, St) -> @@ -2381,7 +2402,7 @@ is_valid_call(Call) -> _ -> true end. -%% is_valid_map_key(K,St) -> true | false +%% is_valid_map_key(K) -> true | false %% variables are allowed for patterns only at the top of the tree is_valid_map_key({var,_,_}) -> true; @@ -3413,6 +3434,14 @@ warn_unused_vars(U, Vt, St0) -> UVt = map(fun ({V,{State,_,Ls}}) -> {V,{State,used,Ls}} end, U), {vtmerge(Vt, UVt), St1}. + +is_var_bound(V, Vt) -> + case orddict:find(V, Vt) of + {ok,{bound,_Usage,_}} -> true; + _ -> false + end. + + %% vtupdate(UpdVarTable, VarTable) -> VarTable. %% Add the variables in the updated vartable to VarTable. The variables %% will be updated with their property in UpdVarTable. The state of diff --git a/lib/stdlib/src/proc_lib.erl b/lib/stdlib/src/proc_lib.erl index 3f79ed0f87..fdc2ae4070 100644 --- a/lib/stdlib/src/proc_lib.erl +++ b/lib/stdlib/src/proc_lib.erl @@ -48,7 +48,9 @@ | {'priority', priority_level()} | {'min_heap_size', non_neg_integer()} | {'min_bin_vheap_size', non_neg_integer()} - | {'fullsweep_after', non_neg_integer()}. + | {'fullsweep_after', non_neg_integer()} + | {'message_queue_data', + 'off_heap' | 'on_heap' | 'mixed' }. -type dict_or_pid() :: pid() | (ProcInfo :: [_]) diff --git a/lib/stdlib/test/erl_lint_SUITE.erl b/lib/stdlib/test/erl_lint_SUITE.erl index 6fea198af3..b0214e5238 100644 --- a/lib/stdlib/test/erl_lint_SUITE.erl +++ b/lib/stdlib/test/erl_lint_SUITE.erl @@ -33,47 +33,38 @@ -define(privdir, proplists:get_value(priv_dir, Conf)). -endif. --export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1, - init_per_group/2,end_per_group/2, - init_per_testcase/2, end_per_testcase/2]). - --export([ - unused_vars_warn_basic/1, - unused_vars_warn_lc/1, - unused_vars_warn_rec/1, - unused_vars_warn_fun/1, - unused_vars_OTP_4858/1, - unused_unsafe_vars_warn/1, - export_vars_warn/1, - shadow_vars/1, - unused_import/1, - unused_function/1, - unsafe_vars/1,unsafe_vars2/1, - unsafe_vars_try/1, - unsized_binary_in_bin_gen_pattern/1, - guard/1, otp_4886/1, otp_4988/1, otp_5091/1, otp_5276/1, otp_5338/1, - otp_5362/1, otp_5371/1, otp_7227/1, otp_5494/1, otp_5644/1, otp_5878/1, - otp_5917/1, otp_6585/1, otp_6885/1, otp_10436/1, otp_11254/1, - otp_11772/1, otp_11771/1, otp_11872/1, - export_all/1, - bif_clash/1, - behaviour_basic/1, behaviour_multiple/1, otp_11861/1, - otp_7550/1, - otp_8051/1, - format_warn/1, - on_load_successful/1, on_load_failing/1, - too_many_arguments/1, - basic_errors/1,bin_syntax_errors/1, - predef/1, - maps/1,maps_type/1,otp_11851/1,otp_11879/1,otp_13230/1, - record_errors/1 - ]). - -init_per_testcase(_Case, Config) -> - Config. - -end_per_testcase(_Case, _Config) -> - ok. +-export([all/0, suite/0, groups/0]). + +-export([unused_vars_warn_basic/1, + unused_vars_warn_lc/1, + unused_vars_warn_rec/1, + unused_vars_warn_fun/1, + unused_vars_OTP_4858/1, + unused_unsafe_vars_warn/1, + export_vars_warn/1, + shadow_vars/1, + unused_import/1, + unused_function/1, + unsafe_vars/1,unsafe_vars2/1, + unsafe_vars_try/1, + unsized_binary_in_bin_gen_pattern/1, + guard/1, otp_4886/1, otp_4988/1, otp_5091/1, otp_5276/1, otp_5338/1, + otp_5362/1, otp_5371/1, otp_7227/1, otp_5494/1, otp_5644/1, otp_5878/1, + otp_5917/1, otp_6585/1, otp_6885/1, otp_10436/1, otp_11254/1, + otp_11772/1, otp_11771/1, otp_11872/1, + export_all/1, + bif_clash/1, + behaviour_basic/1, behaviour_multiple/1, otp_11861/1, + otp_7550/1, + otp_8051/1, + format_warn/1, + on_load_successful/1, on_load_failing/1, + too_many_arguments/1, + basic_errors/1,bin_syntax_errors/1, + predef/1, + maps/1,maps_type/1,maps_parallel_match/1, + otp_11851/1,otp_11879/1,otp_13230/1, + record_errors/1]). suite() -> [{ct_hooks,[ts_install_cth]}, @@ -91,7 +82,8 @@ all() -> bif_clash, behaviour_basic, behaviour_multiple, otp_11861, otp_7550, otp_8051, format_warn, {group, on_load}, too_many_arguments, basic_errors, bin_syntax_errors, predef, - maps, maps_type, otp_11851, otp_11879, otp_13230, + maps, maps_type, maps_parallel_match, + otp_11851, otp_11879, otp_13230, record_errors]. groups() -> @@ -101,19 +93,6 @@ groups() -> unused_vars_OTP_4858, unused_unsafe_vars_warn]}, {on_load, [], [on_load_successful, on_load_failing]}]. -init_per_suite(Config) -> - Config. - -end_per_suite(_Config) -> - ok. - -init_per_group(_GroupName, Config) -> - Config. - -end_per_group(_GroupName, Config) -> - Config. - - %% Warnings for unused variables in some simple cases. unused_vars_warn_basic(Config) when is_list(Config) -> @@ -3583,8 +3562,6 @@ predef(Config) when is_list(Config) -> ok. maps(Config) -> - %% TODO: test key patterns, not done because map patterns are going to be - %% changed a lot. Ts = [{illegal_map_construction, <<"t() -> #{ a := b, @@ -3626,6 +3603,26 @@ maps(Config) -> {errors,[{1,erl_lint,illegal_map_construction}, {1,erl_lint,{unbound_var,'X'}}], []}}, + {legal_map_pattern, + <<" + -record(mapkey, {a=1,b=2}). + t(M,K1) -> + #{ a := 1, + $a := 1, $z := 99, + #{a=>val} := 2, + K1 := 1337, + #mapkey{a = 10} := wat, + #{{a,val}=>val} := 2, + #{ \"hi\" => wazzup, hi => ho } := yep, + ok := 1.0, + [3+3] := nope, + 1.0 := yep, + {3.0+3} := nope, + {yep} := yep + } = M. + ">>, + [], + []}, {legal_map_construction, <<"t(V) -> #{ a => 1, #{a=>V} => 2, @@ -3692,6 +3689,51 @@ maps_type(Config) when is_list(Config) -> [] = run(Config, Ts), ok. +maps_parallel_match(Config) when is_list(Config) -> + Ts = [{parallel_map_patterns_unbound1, + <<" + t(#{} = M) -> + #{K := V} = #{k := K} = M, + V. + ">>, + [], + {errors,[{3,erl_lint,{unbound_var,'K'}}],[]}}, + {parallel_map_patterns_unbound2, + <<" + t(#{} = M) -> + #{K1 := V1} = + #{K2 := V2} = + #{k1 := K1,k2 := K2} = M, + [V1,V2]. + ">>, + [], + {errors,[{3,erl_lint,{unbound_var,'K1'}}, + {3,erl_lint,{unbound_var,'K1'}}, + {4,erl_lint,{unbound_var,'K2'}}, + {4,erl_lint,{unbound_var,'K2'}}],[]}}, + {parallel_map_patterns_bound, + <<" + t(#{} = M,K1,K2) -> + #{K1 := V1} = + #{K2 := V2} = + #{k1 := K1,k2 := K2} = M, + [V1,V2]. + ">>, + [], + []}, + {parallel_map_patterns_literal, + <<" + t(#{} = M) -> + #{k1 := V1} = + #{k2 := V2} = + #{k1 := V1,k2 := V2} = M, + [V1,V2]. + ">>, + [], + []}], + [] = run(Config, Ts), + ok. + %% OTP-11851: More atoms can be used as type names + bug fixes. otp_11851(Config) when is_list(Config) -> Ts = [ |