aboutsummaryrefslogtreecommitdiffstats
path: root/erts/emulator/beam/erl_process.c
diff options
context:
space:
mode:
authorLukas Larsson <[email protected]>2019-03-25 11:45:50 +0100
committerLukas Larsson <[email protected]>2019-03-25 16:34:11 +0100
commit7149d49992fb1a13c6753638733b59015c28c0a5 (patch)
treebab0bec326cffe0c5530b337d74c701db1e5b601 /erts/emulator/beam/erl_process.c
parentef8db1270fc26dfad1ff467ee0acc87439d2c756 (diff)
downloadotp-7149d49992fb1a13c6753638733b59015c28c0a5.tar.gz
otp-7149d49992fb1a13c6753638733b59015c28c0a5.tar.bz2
otp-7149d49992fb1a13c6753638733b59015c28c0a5.zip
erts: Fix so that exit/down terms stay alive
When the GC is run or the link/monitor node is deleted, the terms associated with it will also be deallocated so we have to make sure that we don't do any GCs and that all link/monitor nodes are copied onto the heap before the node is deallocated.
Diffstat (limited to 'erts/emulator/beam/erl_process.c')
-rw-r--r--erts/emulator/beam/erl_process.c43
1 files changed, 33 insertions, 10 deletions
diff --git a/erts/emulator/beam/erl_process.c b/erts/emulator/beam/erl_process.c
index f34289339f..6a0c5bde58 100644
--- a/erts/emulator/beam/erl_process.c
+++ b/erts/emulator/beam/erl_process.c
@@ -12090,9 +12090,11 @@ erts_proc_exit_handle_dist_monitor(ErtsMonitor *mon, void *vctxt, Sint reds)
ErtsDSigSendContext ctx;
ErtsMonLnkDist *dist;
DistEntry *dep;
- Eterm watcher;
+ Eterm watcher, ref, *hp;
ErtsMonitorData *mdp = NULL;
Eterm watched;
+ Uint watcher_sz, ref_sz;
+ ErtsHeapFactory factory;
ASSERT(erts_monitor_is_target(mon) && mon->type == ERTS_MON_TYPE_DIST_PROC);
@@ -12124,10 +12126,18 @@ erts_proc_exit_handle_dist_monitor(ErtsMonitor *mon, void *vctxt, Sint reds)
case ERTS_DSIG_PREP_CONNECTED:
if (dist->connection_id != ctx.connection_id)
break;
+ erts_factory_proc_init(&factory, c_p);
+ watcher_sz = size_object(watcher);
+ hp = erts_produce_heap(&factory, watcher_sz, 0);
+ watcher = copy_struct(watcher, watcher_sz, &hp, factory.off_heap);
+ ref_sz = size_object(mdp->ref);
+ hp = erts_produce_heap(&factory, ref_sz, 0);
+ ref = copy_struct(mdp->ref, ref_sz, &hp, factory.off_heap);
+ erts_factory_close(&factory);
code = erts_dsig_send_m_exit(&ctx,
watcher,
watched,
- mdp->ref,
+ ref,
reason);
switch (code) {
case ERTS_DSIG_SEND_CONTINUE:
@@ -12332,13 +12342,15 @@ erts_proc_exit_handle_dist_link(ErtsLink *lnk, void *vctxt, Sint reds)
{
ErtsProcExitContext *ctxt = (ErtsProcExitContext *) vctxt;
Process *c_p = ctxt->c_p;
- Eterm reason = ctxt->reason;
+ Eterm reason = ctxt->reason, item, *hp;
+ Uint item_sz;
int code;
ErtsDSigSendContext ctx;
ErtsMonLnkDist *dist;
DistEntry *dep;
ErtsLink *dlnk;
ErtsLinkData *ldp = NULL;
+ ErtsHeapFactory factory;
ASSERT(lnk->type == ERTS_LNK_TYPE_DIST_PROC);
dlnk = erts_link_to_other(lnk, &ldp);
@@ -12365,9 +12377,14 @@ erts_proc_exit_handle_dist_link(ErtsLink *lnk, void *vctxt, Sint reds)
case ERTS_DSIG_PREP_CONNECTED:
if (dist->connection_id != ctx.connection_id)
break;
+ erts_factory_proc_init(&factory, c_p);
+ item_sz = size_object(lnk->other.item);
+ hp = erts_produce_heap(&factory, item_sz, 0);
+ item = copy_struct(lnk->other.item, item_sz, &hp, factory.off_heap);
+ erts_factory_close(&factory);
code = erts_dsig_send_exit_tt(&ctx,
c_p->common.id,
- lnk->other.item,
+ item,
reason,
SEQ_TRACE_TOKEN(c_p));
switch (code) {
@@ -12584,6 +12601,8 @@ erts_continue_exit_process(Process *p)
if (p->u.terminate) {
trap_state = p->u.terminate;
+ /* Re-set the reason as it may have been gc:ed */
+ trap_state->reason = p->fvalue;
} else {
trap_state->phase = ERTS_CONTINUE_EXIT_TIMERS;
trap_state->reason = p->fvalue;
@@ -12661,11 +12680,11 @@ restart:
p->flags &= ~F_USING_DB;
}
- erts_set_gc_state(p, 1);
-
trap_state->phase = ERTS_CONTINUE_EXIT_CLEAN_SYS_TASKS;
case ERTS_CONTINUE_EXIT_CLEAN_SYS_TASKS:
-
+
+ /* We enable GC again as it can produce more sys-tasks */
+ erts_set_gc_state(p, 1);
state = erts_atomic32_read_acqb(&p->state);
if ((state & ERTS_PSFLG_SYS_TASKS) || p->dirty_sys_tasks) {
reds -= cleanup_sys_tasks(p, state, reds);
@@ -12788,6 +12807,9 @@ restart:
erts_deref_dist_entry(trap_state->dep);
}
+ /* Disable GC so that reason does not get moved */
+ erts_set_gc_state(p, 0);
+
trap_state->pectxt.c_p = p;
trap_state->pectxt.reason = trap_state->reason;
trap_state->pectxt.dist_links = NULL;
@@ -12878,7 +12900,7 @@ restart:
goto yield;
}
}
- erts_set_gc_state(p, 1);
+
trap_state->pectxt.dist_state = NIL;
if (reds <= 0)
goto yield;
@@ -12917,11 +12939,12 @@ restart:
* From this point on we are no longer allowed to yield
* this process.
*/
-
#ifdef DEBUG
yield_allowed = 0;
#endif
+ erts_set_gc_state(p, 1);
+
/* Set state to not active as we don't want this process
to be scheduled in again after this. */
state = erts_atomic32_read_band_relb(&p->state,
@@ -12960,7 +12983,7 @@ restart:
erts_free(ERTS_ALC_T_CONT_EXIT_TRAP, trap_state);
p->u.terminate = NULL;
}
-
+
ERTS_CHK_HAVE_ONLY_MAIN_PROC_LOCK(p);
if (IS_TRACED_FL(p, F_TRACE_SCHED_EXIT))