diff options
author | Rickard Green <[email protected]> | 2019-07-16 16:13:11 +0200 |
---|---|---|
committer | Rickard Green <[email protected]> | 2019-07-22 11:20:54 +0200 |
commit | e4f300da5371660cc8ccdf977b31925500bc41a0 (patch) | |
tree | 838a8a82bad942014290f660d3e99468cfae39b1 | |
parent | da6cfb60e3390816d87bf5feee31396e49b2a074 (diff) | |
download | otp-e4f300da5371660cc8ccdf977b31925500bc41a0.tar.gz otp-e4f300da5371660cc8ccdf977b31925500bc41a0.tar.bz2 otp-e4f300da5371660cc8ccdf977b31925500bc41a0.zip |
Fix node refc test for free processes hanging around
-rw-r--r-- | erts/emulator/beam/erl_monitor_link.c | 49 | ||||
-rw-r--r-- | erts/emulator/beam/erl_monitor_link.h | 17 | ||||
-rw-r--r-- | erts/emulator/beam/erl_node_tables.c | 153 | ||||
-rw-r--r-- | erts/emulator/beam/erl_process.c | 76 | ||||
-rw-r--r-- | erts/emulator/beam/erl_process.h | 7 |
5 files changed, 233 insertions, 69 deletions
diff --git a/erts/emulator/beam/erl_monitor_link.c b/erts/emulator/beam/erl_monitor_link.c index 1c6b4afaa3..43028be39d 100644 --- a/erts/emulator/beam/erl_monitor_link.c +++ b/erts/emulator/beam/erl_monitor_link.c @@ -671,6 +671,24 @@ erts_monitor_tree_foreach(ErtsMonitor *root, arg); } +void +erts_debug_monitor_tree_destroying_foreach(ErtsMonitor *root, + ErtsMonitorFunc func, + void *arg, + void *vysp) +{ + void *tmp_vysp = erts_alloc(ERTS_ALC_T_ML_YIELD_STATE, + sizeof(ErtsMonLnkYieldState)); + Sint reds; + sys_memcpy(tmp_vysp, tmp_vysp, sizeof(ErtsMonLnkYieldState)); + do { + reds = ml_rbt_foreach_yielding((ErtsMonLnkNode *) root, + (ErtsMonLnkNodeFunc) func, + arg, &tmp_vysp, (Sint) INT_MAX); + } while (reds <= 0); + ERTS_ML_ASSERT(!tmp_vysp); +} + int erts_monitor_tree_foreach_yielding(ErtsMonitor *root, ErtsMonitorFunc func, @@ -716,6 +734,19 @@ erts_monitor_list_foreach(ErtsMonitor *list, arg, &ystate, (Sint) INT_MAX)); } +void +erts_debug_monitor_list_destroying_foreach(ErtsMonitor *list, + ErtsMonitorFunc func, + void *arg, + void *vysp) +{ + void *tmp_vysp = vysp; + while (!ml_dl_list_foreach_yielding((ErtsMonLnkNode *) list, + (int (*)(ErtsMonLnkNode *, void *, Sint)) func, + arg, &tmp_vysp, (Sint) INT_MAX)); + ERTS_ML_ASSERT(!tmp_vysp); +} + int erts_monitor_list_foreach_yielding(ErtsMonitor *list, ErtsMonitorFunc func, @@ -1080,6 +1111,24 @@ erts_link_tree_foreach(ErtsLink *root, } +void +erts_debug_link_tree_destroying_foreach(ErtsLink *root, + ErtsLinkFunc func, + void *arg, + void *vysp) +{ + void *tmp_vysp = erts_alloc(ERTS_ALC_T_ML_YIELD_STATE, + sizeof(ErtsMonLnkYieldState)); + Sint reds; + sys_memcpy(tmp_vysp, vysp, sizeof(ErtsMonLnkYieldState)); + do { + reds = ml_rbt_foreach_yielding((ErtsMonLnkNode *) root, + (ErtsMonLnkNodeFunc) func, + arg, &tmp_vysp, (Sint) INT_MAX); + } while (reds <= 0); + ERTS_ML_ASSERT(!tmp_vysp); +} + int erts_link_tree_foreach_yielding(ErtsLink *root, ErtsLinkFunc func, diff --git a/erts/emulator/beam/erl_monitor_link.h b/erts/emulator/beam/erl_monitor_link.h index eff861fce8..86be400c09 100644 --- a/erts/emulator/beam/erl_monitor_link.h +++ b/erts/emulator/beam/erl_monitor_link.h @@ -1509,6 +1509,17 @@ ERTS_GLB_INLINE ErtsMonitorSuspend *erts_monitor_suspend(ErtsMonitor *mon) #endif +void +erts_debug_monitor_tree_destroying_foreach(ErtsMonitor *root, + ErtsMonitorFunc func, + void *arg, + void *vysp); +void +erts_debug_monitor_list_destroying_foreach(ErtsMonitor *list, + ErtsMonitorFunc func, + void *arg, + void *vysp); + /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\ * Link Operations * \* */ @@ -2365,4 +2376,10 @@ erts_link_dist_delete(ErtsLink *lnk) #endif /* ERTS_GLB_INLINE_INCL_FUNC_DEF */ +void +erts_debug_link_tree_destroying_foreach(ErtsLink *root, + ErtsLinkFunc func, + void *arg, + void *vysp); + #endif /* ERL_MONITOR_LINK_H__ */ diff --git a/erts/emulator/beam/erl_node_tables.c b/erts/emulator/beam/erl_node_tables.c index bdf30ef496..50e9812534 100644 --- a/erts/emulator/beam/erl_node_tables.c +++ b/erts/emulator/beam/erl_node_tables.c @@ -1200,7 +1200,7 @@ static Eterm AM_persistent_term; static void setup_reference_table(void); static Eterm reference_table_term(Uint **hpp, ErlOffHeap *ohp, Uint *szp); static void delete_reference_table(void); -static void cleanup_system(void); +static void clear_system(void); #undef ERTS_MAX__ #define ERTS_MAX__(A, B) ((A) > (B) ? (A) : (B)) @@ -1323,7 +1323,7 @@ erts_get_node_and_dist_references(struct process *proc) delete_reference_table(); #endif - cleanup_system(); + clear_system(); erts_thr_progress_unblock(); erts_proc_lock(proc, ERTS_PROC_LOCK_MAIN); @@ -1594,18 +1594,6 @@ static int clear_visited_monitor(ErtsMonitor *mon, void *p, Sint reds) } static void -insert_p_monitors(ErtsPTabElementCommon *p) -{ - Eterm id = p->id; - erts_monitor_tree_foreach(p->u.alive.monitors, - insert_monitor, - (void *) &id); - erts_monitor_list_foreach(p->u.alive.lt_monitors, - insert_monitor, - (void *) &id); -} - -static void insert_dist_monitors(DistEntry *dep) { if (dep->mld) { @@ -1635,17 +1623,6 @@ insert_dist_sequences(DistEntry *dep) } static void -clear_visited_p_monitors(ErtsPTabElementCommon *p) -{ - erts_monitor_tree_foreach(p->u.alive.monitors, - clear_visited_monitor, - NULL); - erts_monitor_list_foreach(p->u.alive.lt_monitors, - clear_visited_monitor, - NULL); -} - -static void clear_visited_dist_monitors(DistEntry *dep) { if (dep->mld) { @@ -1689,13 +1666,6 @@ static int clear_visited_link(ErtsLink *lnk, void *p, Sint reds) } static void -insert_p_links(ErtsPTabElementCommon *p) -{ - Eterm id = p->id; - erts_link_tree_foreach(p->u.alive.links, insert_link, (void *) &id); -} - -static void insert_dist_links(DistEntry *dep) { if (dep->mld) @@ -1705,14 +1675,6 @@ insert_dist_links(DistEntry *dep) } static void -clear_visited_p_links(ErtsPTabElementCommon *p) -{ - erts_link_tree_foreach(p->u.alive.links, - clear_visited_link, - NULL); -} - -static void clear_visited_dist_links(DistEntry *dep) { if (dep->mld) @@ -1907,15 +1869,11 @@ insert_process(Process *proc) insert_sig_ext, (void *) proc); - /* If the process is FREE, the proc->common field has been - re-used by the ptab delete, so we cannot trust it. */ - if (!(erts_atomic32_read_nob(&proc->state) & ERTS_PSFLG_FREE)) { - /* Insert links */ - insert_p_links(&proc->common); - - /* Insert monitors */ - insert_p_monitors(&proc->common); - } + /* Insert monitors and links... */ + erts_debug_proc_monitor_link_foreach(proc, + insert_monitor, + insert_link, + (void *) &proc->common.id); { DistEntry *dep = ERTS_PROC_GET_DIST_ENTRY(proc); @@ -1928,6 +1886,12 @@ insert_process(Process *proc) } static void +insert_process2(Process *proc, void *arg) +{ + insert_process(proc); +} + +static void insert_dist_suspended_procs(DistEntry *dep) { ErtsProcList *plist = erts_proclist_peek_first(dep->suspended); @@ -1938,6 +1902,19 @@ insert_dist_suspended_procs(DistEntry *dep) } } +static void clear_process(Process *proc); + +static void +clear_dist_suspended_procs(DistEntry *dep) +{ + ErtsProcList *plist = erts_proclist_peek_first(dep->suspended); + while (plist) { + if (is_not_immed(plist->u.pid)) + clear_process(plist->u.p); + plist = erts_proclist_peek_next(dep->suspended, plist); + } +} + static void insert_persistent_term(ErlOffHeap *ohp, void *arg) { @@ -2030,7 +2007,8 @@ setup_reference_table(void) if (proc) insert_process(proc); } - + erts_debug_free_process_foreach(insert_process2, NULL); + erts_debug_foreach_sys_msg_in_q(insert_sys_msg); /* Insert all ports */ @@ -2048,10 +2026,18 @@ setup_reference_table(void) if (state & ERTS_PORT_SFLGS_DEAD) continue; - /* Insert links */ - insert_p_links(&prt->common); - /* Insert monitors */ - insert_p_monitors(&prt->common); + /* Insert links */ + erts_link_tree_foreach(ERTS_P_LINKS(prt), + insert_link, + (void *) &prt->common.id); + /* Insert monitors */ + erts_monitor_tree_foreach(ERTS_P_MONITORS(prt), + insert_monitor, + (void *) &prt->common.id); + /* Insert local target monitors */ + erts_monitor_list_foreach(ERTS_P_LT_MONITORS(prt), + insert_monitor, + (void *) &prt->common.id); /* Insert port data */ ohp = erts_port_data_offheap(prt); if (ohp) @@ -2431,28 +2417,43 @@ delete_reference_table(void) } } +static void clear_process(Process *proc) +{ + erts_proc_sig_debug_foreach_sig(proc, + noop_sig_msg, + noop_sig_offheap, + clear_visited_monitor, + clear_visited_link, + noop_sig_ext, + (void *) proc); + + + /* Clear monitors and links... */ + erts_debug_proc_monitor_link_foreach(proc, + clear_visited_monitor, + clear_visited_link, + (void *) &proc->common.id); +} + +static void clear_process2(Process *proc, void *arg) +{ + clear_process(proc); +} + static void -cleanup_system(void) +clear_system(void) { DistEntry *dep; int i, max; - /* Cleanup... */ + /* Clear... */ max = erts_ptab_max(&erts_proc); for (i = 0; i < max; i++) { Process *proc = erts_pix2proc(i); - if (proc) { - clear_visited_p_links(&proc->common); - clear_visited_p_monitors(&proc->common); - erts_proc_sig_debug_foreach_sig(proc, - noop_sig_msg, - noop_sig_offheap, - clear_visited_monitor, - clear_visited_link, - noop_sig_ext, - (void *) proc); - } + if (proc) + clear_process(proc); } + erts_debug_free_process_foreach(clear_process2, NULL); max = erts_ptab_max(&erts_port); for (i = 0; i < max; i++) { @@ -2467,28 +2468,42 @@ cleanup_system(void) if (state & ERTS_PORT_SFLGS_DEAD) continue; - clear_visited_p_links(&prt->common); - clear_visited_p_monitors(&prt->common); + /* Clear links */ + erts_link_tree_foreach(ERTS_P_LINKS(prt), + clear_visited_link, + (void *) &prt->common.id); + /* Clear monitors */ + erts_monitor_tree_foreach(ERTS_P_MONITORS(prt), + clear_visited_monitor, + (void *) &prt->common.id); + /* Clear local target monitors */ + erts_monitor_list_foreach(ERTS_P_LT_MONITORS(prt), + clear_visited_monitor, + (void *) &prt->common.id); } for(dep = erts_visible_dist_entries; dep; dep = dep->next) { clear_visited_dist_links(dep); clear_visited_dist_monitors(dep); + clear_dist_suspended_procs(dep); } for(dep = erts_hidden_dist_entries; dep; dep = dep->next) { clear_visited_dist_links(dep); clear_visited_dist_monitors(dep); + clear_dist_suspended_procs(dep); } for(dep = erts_pending_dist_entries; dep; dep = dep->next) { clear_visited_dist_links(dep); clear_visited_dist_monitors(dep); + clear_dist_suspended_procs(dep); } for(dep = erts_not_connected_dist_entries; dep; dep = dep->next) { clear_visited_dist_links(dep); clear_visited_dist_monitors(dep); + clear_dist_suspended_procs(dep); } } diff --git a/erts/emulator/beam/erl_process.c b/erts/emulator/beam/erl_process.c index 1f6adb98ef..994876e796 100644 --- a/erts/emulator/beam/erl_process.c +++ b/erts/emulator/beam/erl_process.c @@ -13495,3 +13495,79 @@ erts_debug_later_op_foreach(void (*callback)(void*), } } } + +void +erts_debug_free_process_foreach(void (*func)(Process *, void *), void *arg) +{ + ErtsRunQueue *rq; + int ix, prio; + for (ix = 0; ix < erts_no_run_queues; ix++) { + rq = ERTS_RUNQ_IX(ix); + for (prio = PRIORITY_MAX; prio < PRIORITY_LOW; prio++) { + Process *p = rq->procs.prio[prio].first; + for (; p; p = p->next) { + if (ERTS_PSFLG_FREE & erts_atomic32_read_nob(&p->state)) + (*func)(p, arg); + } + } + } +} + +void +erts_debug_proc_monitor_link_foreach(Process *proc, + int (*monitor_func)(ErtsMonitor *, void *, Sint ), + int (*link_func)(ErtsLink *, void *, Sint ), + void *arg) +{ + if (!(erts_atomic32_read_nob(&proc->state) & ERTS_PSFLG_FREE)) { + /* For all links */ + erts_link_tree_foreach(ERTS_P_LINKS(proc), + link_func, + arg); + /* For all monitors */ + erts_monitor_tree_foreach(ERTS_P_MONITORS(proc), + monitor_func, + arg); + /* For all local target monitors */ + erts_monitor_list_foreach(ERTS_P_LT_MONITORS(proc), + monitor_func, + arg); + } + else { + struct continue_exit_state *ce_state = proc->u.terminate; + + /* For all links */ + if (ce_state->phase == ERTS_CONTINUE_EXIT_LINKS) + erts_debug_link_tree_destroying_foreach(ce_state->links, + link_func, + arg, + ce_state->yield_state); + else + erts_link_tree_foreach(ce_state->links, + link_func, + arg); + + /* For all monitors */ + if (ce_state->phase == ERTS_CONTINUE_EXIT_MONITORS) + erts_debug_monitor_tree_destroying_foreach(ce_state->monitors, + monitor_func, + arg, + ce_state->yield_state); + else + erts_monitor_tree_foreach(ce_state->monitors, + monitor_func, + arg); + + /* For all local target monitors */ + if (ce_state->phase == ERTS_CONTINUE_EXIT_LT_MONITORS) + erts_debug_monitor_list_destroying_foreach(ce_state->lt_monitors, + monitor_func, + arg, + ce_state->yield_state); + else + erts_monitor_list_foreach(ce_state->lt_monitors, + monitor_func, + arg); + + } +} diff --git a/erts/emulator/beam/erl_process.h b/erts/emulator/beam/erl_process.h index cdad72443f..f67f567705 100644 --- a/erts/emulator/beam/erl_process.h +++ b/erts/emulator/beam/erl_process.h @@ -701,6 +701,13 @@ void erts_debug_later_op_foreach(void (*callback)(void*), void (*func)(void *, ErtsThrPrgrVal, void *), void *arg); +void +erts_debug_free_process_foreach(void (*func)(Process *, void *), void *arg); +void +erts_debug_proc_monitor_link_foreach(Process *proc, + int (*monitor_func)(ErtsMonitor *, void *, Sint ), + int (*link_func)(ErtsLink *, void *, Sint ), + void *arg); #ifdef ERTS_INCLUDE_SCHEDULER_INTERNALS |