diff options
Diffstat (limited to 'erts')
-rw-r--r-- | erts/doc/src/erlang.xml | 7 | ||||
-rw-r--r-- | erts/emulator/beam/dist.c | 2 | ||||
-rw-r--r-- | erts/emulator/beam/erl_db_util.c | 2 | ||||
-rw-r--r-- | erts/emulator/beam/erl_init.c | 1 | ||||
-rw-r--r-- | erts/emulator/beam/erl_port.h | 6 | ||||
-rw-r--r-- | erts/emulator/beam/erl_port_task.c | 66 | ||||
-rw-r--r-- | erts/emulator/beam/io.c | 18 | ||||
-rw-r--r-- | erts/emulator/test/match_spec_SUITE.erl | 16 | ||||
-rw-r--r-- | erts/preloaded/ebin/erlang.beam | bin | 92736 -> 92756 bytes | |||
-rw-r--r-- | erts/preloaded/src/erlang.erl | 2 |
10 files changed, 91 insertions, 29 deletions
diff --git a/erts/doc/src/erlang.xml b/erts/doc/src/erlang.xml index 2faa46d760..1d67be2e52 100644 --- a/erts/doc/src/erlang.xml +++ b/erts/doc/src/erlang.xml @@ -3706,10 +3706,11 @@ os_prompt% </pre> the initial function call with which the process was spawned.</p> </item> - <tag><c>{links, <anno>Pids</anno>}</c></tag> + <tag><c>{links, <anno>PidsAndPorts</anno>}</c></tag> <item> - <p><c><anno>Pids</anno></c> is a list of pids, with processes to - which the process has a link.</p> + <p><c><anno>PidsAndPorts</anno></c> is a list of pids and + port identifiers, with processes or ports to which the process + has a link.</p> </item> <tag><c>{last_calls, false|Calls}</c></tag> <item> diff --git a/erts/emulator/beam/dist.c b/erts/emulator/beam/dist.c index f169a1a34a..64cd93a100 100644 --- a/erts/emulator/beam/dist.c +++ b/erts/emulator/beam/dist.c @@ -67,7 +67,7 @@ dist_msg_dbg(ErtsDistExternal *edep, char *what, byte *buf, int sz) { byte *extp = edep->extp; Eterm msg; - Sint size = erts_decode_dist_ext_size(edep, 0); + Sint size = erts_decode_dist_ext_size(edep); if (size < 0) { erts_fprintf(stderr, "DIST MSG DEBUG: erts_decode_dist_ext_size(%s) failed:\n", diff --git a/erts/emulator/beam/erl_db_util.c b/erts/emulator/beam/erl_db_util.c index bcdb630140..bb08762b26 100644 --- a/erts/emulator/beam/erl_db_util.c +++ b/erts/emulator/beam/erl_db_util.c @@ -5009,7 +5009,7 @@ static Eterm match_spec_test(Process *p, Eterm against, Eterm spec, int trace) static Eterm seq_trace_fake(Process *p, Eterm arg1) { Eterm result = erl_seq_trace_info(p, arg1); - if (is_tuple(result) && *tuple_val(result) == 2) { + if (!is_non_value(result) && is_tuple(result) && *tuple_val(result) == 2) { return (tuple_val(result))[2]; } return result; diff --git a/erts/emulator/beam/erl_init.c b/erts/emulator/beam/erl_init.c index 175f04b15b..8cdf954dd2 100644 --- a/erts/emulator/beam/erl_init.c +++ b/erts/emulator/beam/erl_init.c @@ -989,6 +989,7 @@ erl_start(int argc, char **argv) break; case 'a': erts_set_user_requested_filename_encoding(ERL_FILENAME_UNKNOWN); + break; default: erts_fprintf(stderr, "bad filename encoding %s, can be (l,u or a)\n", arg); erts_usage(); diff --git a/erts/emulator/beam/erl_port.h b/erts/emulator/beam/erl_port.h index f4d73e716a..fb07f3d5bc 100644 --- a/erts/emulator/beam/erl_port.h +++ b/erts/emulator/beam/erl_port.h @@ -430,7 +430,7 @@ ERTS_GLB_INLINE void erts_port_release(Port *); ERTS_GLB_INLINE Port *erts_thr_id2port_sflgs(Eterm id, Uint32 invalid_sflgs); ERTS_GLB_INLINE void erts_thr_port_release(Port *prt); #endif -ERTS_GLB_INLINE Port *erts_thr_drvport2port_raw(ErlDrvPort); +ERTS_GLB_INLINE Port *erts_thr_drvport2port_raw(ErlDrvPort, int); ERTS_GLB_INLINE Port *erts_drvport2port_raw(ErlDrvPort drvport); ERTS_GLB_INLINE Port *erts_drvport2port(ErlDrvPort, erts_aint32_t *); ERTS_GLB_INLINE Port *erts_drvportid2port(Eterm); @@ -622,7 +622,7 @@ erts_thr_port_release(Port *prt) #endif ERTS_GLB_INLINE Port* -erts_thr_drvport2port_raw(ErlDrvPort drvport) +erts_thr_drvport2port_raw(ErlDrvPort drvport, int lock_pdl) { #if ERTS_ENABLE_LOCK_CHECK int emu_thread = erts_lc_is_emu_thr(); @@ -631,6 +631,8 @@ erts_thr_drvport2port_raw(ErlDrvPort drvport) return NULL; else { Port *prt = (Port *) drvport; + if (lock_pdl && prt->port_data_lock) + driver_pdl_lock(prt->port_data_lock); #if ERTS_ENABLE_LOCK_CHECK if (!ERTS_IS_CRASH_DUMPING) { if (emu_thread) { diff --git a/erts/emulator/beam/erl_port_task.c b/erts/emulator/beam/erl_port_task.c index b661c26036..8ceadcdb8c 100644 --- a/erts/emulator/beam/erl_port_task.c +++ b/erts/emulator/beam/erl_port_task.c @@ -120,7 +120,9 @@ struct ErtsPortTaskBusyCallerTable_ { }; -static void begin_port_cleanup(Port *pp, ErtsPortTask **execq); +static void begin_port_cleanup(Port *pp, + ErtsPortTask **execq, + int *processing_busy_q_p); ERTS_SCHED_PREF_QUICK_ALLOC_IMPL(port_task, ErtsPortTask, @@ -1525,7 +1527,7 @@ erts_port_task_free_port(Port *pp) erts_resume_processes(suspended); if (!(flags & (ERTS_PTS_FLG_IN_RUNQ|ERTS_PTS_FLG_EXEC))) - begin_port_cleanup(pp, NULL); + begin_port_cleanup(pp, NULL, NULL); } /* @@ -1681,8 +1683,7 @@ erts_port_task_execute(ErtsRunQueue *runq, Port **curr_port_pp) begin_handle_tasks: if (state & ERTS_PORT_SFLG_FREE) { reds += ERTS_PORT_REDS_FREE; - - begin_port_cleanup(pp, &execq); + begin_port_cleanup(pp, &execq, &processing_busy_q); break; } @@ -1773,22 +1774,66 @@ release_port(void *vport) #endif static void -begin_port_cleanup(Port *pp, ErtsPortTask **execqp) +begin_port_cleanup(Port *pp, ErtsPortTask **execqp, int *processing_busy_q_p) { int i, max; - ErtsPortTask *qs[2]; + ErtsPortTaskBusyCallerTable *tabp; + ErtsPortTask *qs[3]; ERTS_SMP_LC_ASSERT(erts_lc_is_port_locked(pp)); /* - * Handle remaining tasks... + * Abort remaining tasks... + * + * We want to process queues in the following order in order + * to preserve signal ordering guarantees: + * 1. Local busy queue + * 2. Local queue + * 3. In queue */ max = 0; - if (execqp && *execqp) { - qs[max++] = *execqp; + if (!execqp) { + if (pp->sched.taskq.local.busy.first) + qs[max++] = pp->sched.taskq.local.busy.first; + if (pp->sched.taskq.local.first) + qs[max++] = pp->sched.taskq.local.first; + } + else { + if (*processing_busy_q_p) { + if (*execqp) + qs[max++] = *execqp; + if (pp->sched.taskq.local.first) + qs[max++] = pp->sched.taskq.local.first; + } + else { + if (pp->sched.taskq.local.busy.first) + qs[max++] = pp->sched.taskq.local.busy.first; + if (*execqp) + qs[max++] = *execqp; + } *execqp = NULL; + *processing_busy_q_p = 0; + } + pp->sched.taskq.local.busy.first = NULL; + pp->sched.taskq.local.busy.last = NULL; + pp->sched.taskq.local.first = NULL; + tabp = pp->sched.taskq.local.busy.table; + if (tabp) { + int bix; + for (bix = 0; bix < ERTS_PORT_TASK_BUSY_CALLER_TABLE_BUCKETS; bix++) { + ErtsPortTaskBusyCaller *bcp = tabp->bucket[bix]; + while (bcp) { + ErtsPortTaskBusyCaller *free_bcp = bcp; + bcp = bcp->next; + if (free_bcp != &tabp->pre_alloc_busy_caller) + erts_free(ERTS_ALC_T_BUSY_CALLER, free_bcp); + } + } + + busy_caller_table_free(tabp); + pp->sched.taskq.local.busy.table = NULL; } erts_port_task_sched_lock(&pp->sched); @@ -1875,7 +1920,8 @@ begin_port_cleanup(Port *pp, ErtsPortTask **execqp) } erts_smp_atomic32_read_band_nob(&pp->sched.flags, - ~ERTS_PTS_FLG_HAVE_TASKS); + ~(ERTS_PTS_FLG_HAVE_BUSY_TASKS + |ERTS_PTS_FLG_HAVE_TASKS)); /* * Schedule cleanup of port structure... diff --git a/erts/emulator/beam/io.c b/erts/emulator/beam/io.c index be094862d4..e466f0e299 100644 --- a/erts/emulator/beam/io.c +++ b/erts/emulator/beam/io.c @@ -82,9 +82,11 @@ static void pdl_init(void); #ifdef ERTS_SMP static void driver_monitor_lock_pdl(Port *p); static void driver_monitor_unlock_pdl(Port *p); +#define DRV_MONITOR_LOOKUP_PORT_LOCK_PDL(Port) erts_thr_drvport2port_raw((Port), 1) #define DRV_MONITOR_LOCK_PDL(Port) driver_monitor_lock_pdl(Port) #define DRV_MONITOR_UNLOCK_PDL(Port) driver_monitor_unlock_pdl(Port) #else +#define DRV_MONITOR_LOOKUP_PORT_LOCK_PDL(Port) erts_thr_drvport2port_raw((Port), 0) #define DRV_MONITOR_LOCK_PDL(Port) /* nothing */ #define DRV_MONITOR_UNLOCK_PDL(Port) /* nothing */ #endif @@ -95,7 +97,7 @@ static void driver_monitor_unlock_pdl(Port *p); static ERTS_INLINE ErlIOQueue* drvport2ioq(ErlDrvPort drvport) { - Port *prt = erts_thr_drvport2port_raw(drvport); + Port *prt = erts_thr_drvport2port_raw(drvport, 0); erts_aint32_t state = erts_atomic32_read_nob(&prt->state); if (state & ERTS_PORT_SFLGS_INVALID_DRIVER_LOOKUP) return NULL; @@ -2534,6 +2536,8 @@ port_link_failure(Eterm port_id, Eterm linker) if (IS_TRACED_FL(rp, F_TRACE_PROCS)) trace_proc(NULL, rp, am_getting_unlinked, port_id); } + if (rp_locks) + erts_smp_proc_unlock(rp, rp_locks); } } } @@ -6737,9 +6741,7 @@ int driver_monitor_process(ErlDrvPort drvport, ErtsSchedulerData *sched = erts_get_scheduler_data(); #endif - prt = erts_thr_drvport2port_raw(drvport); - - DRV_MONITOR_LOCK_PDL(prt); + prt = DRV_MONITOR_LOOKUP_PORT_LOCK_PDL(drvport); state = erts_atomic32_read_nob(&prt->state); @@ -6818,9 +6820,7 @@ int driver_demonitor_process(ErlDrvPort drvport, ErtsSchedulerData *sched = erts_get_scheduler_data(); #endif - prt = erts_thr_drvport2port_raw(drvport); - - DRV_MONITOR_LOCK_PDL(prt); + prt = DRV_MONITOR_LOOKUP_PORT_LOCK_PDL(drvport); state = erts_atomic32_read_nob(&prt->state); @@ -6881,9 +6881,7 @@ ErlDrvTermData driver_get_monitored_process(ErlDrvPort drvport, ErtsSchedulerData *sched = erts_get_scheduler_data(); #endif - prt = erts_thr_drvport2port_raw(drvport); - - DRV_MONITOR_LOCK_PDL(prt); + prt = DRV_MONITOR_LOOKUP_PORT_LOCK_PDL(drvport); state = erts_atomic32_read_nob(&prt->state); if (state & ERTS_PORT_SFLGS_INVALID_DRIVER_LOOKUP) { diff --git a/erts/emulator/test/match_spec_SUITE.erl b/erts/emulator/test/match_spec_SUITE.erl index 461773114e..d5cb4ee1b7 100644 --- a/erts/emulator/test/match_spec_SUITE.erl +++ b/erts/emulator/test/match_spec_SUITE.erl @@ -28,7 +28,7 @@ unary_plus/1, unary_minus/1, moving_labels/1]). -export([fpe/1]). -export([otp_9422/1]). - +-export([faulty_seq_trace/1, do_faulty_seq_trace/0]). -export([runner/2, loop_runner/3]). -export([f1/1, f2/2, f3/2, fn/1, fn/2, fn/3]). -export([do_boxed_and_small/0]). @@ -59,6 +59,7 @@ all() -> ms_trace3, boxed_and_small, destructive_in_test_bif, guard_exceptions, unary_plus, unary_minus, fpe, moving_labels, + faulty_seq_trace, otp_9422]; true -> [not_run] end. @@ -726,6 +727,19 @@ do_boxed_and_small() -> {ok, false, _, _} = erlang:match_spec_test({0,3},[{{make_ref(),'_'},[],['$_']}],table), ok. +faulty_seq_trace(doc) -> + ["Test that faulty seq_trace_call does not crash emulator"]; +faulty_seq_trace(suite) -> []; +faulty_seq_trace(Config) when is_list(Config) -> + ?line {ok, Node} = start_node(match_spec_suite_other), + ?line ok = rpc:call(Node,?MODULE,do_faulty_seq_trace,[]), + ?line stop_node(Node), + ok. + +do_faulty_seq_trace() -> + {ok,'EXIT',_,_} = erlang:match_spec_test([],[{'_',[],[{message,{set_seq_token,yxa,true}}]}],trace), + ok. + errchk(Pat) -> case catch erlang:trace_pattern({?MODULE, f2, 2}, Pat) of {'EXIT', {badarg, _}} -> diff --git a/erts/preloaded/ebin/erlang.beam b/erts/preloaded/ebin/erlang.beam Binary files differindex bf37e3c2b2..bea586b11c 100644 --- a/erts/preloaded/ebin/erlang.beam +++ b/erts/preloaded/ebin/erlang.beam diff --git a/erts/preloaded/src/erlang.erl b/erts/preloaded/src/erlang.erl index 739fdde10a..061db72dd8 100644 --- a/erts/preloaded/src/erlang.erl +++ b/erts/preloaded/src/erlang.erl @@ -1756,7 +1756,7 @@ process_flag(_Flag, _Value) -> {group_leader, GroupLeader :: pid()} | {heap_size, Size :: non_neg_integer()} | {initial_call, mfa()} | - {links, Pids :: [pid() | port()]} | + {links, PidsAndPorts :: [pid() | port()]} | {last_calls, false | (Calls :: [mfa()])} | {memory, Size :: non_neg_integer()} | {message_que_len, MessageQueueLen :: non_neg_integer()} | |