Skip to content

Commit f8dfcf6

Browse files
committed
Make sure to GC *before* sending ACTORMSG_BLOCK to CD
1 parent 5f3057c commit f8dfcf6

File tree

1 file changed

+14
-17
lines changed

1 file changed

+14
-17
lines changed

src/libponyrt/actor/actor.c

Lines changed: 14 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -250,17 +250,22 @@ static void send_unblock(pony_actor_t* actor)
250250

251251
static void send_block(pony_ctx_t* ctx, pony_actor_t* actor)
252252
{
253-
// We're blocked, send block message.
254253
pony_assert(ctx->current == actor);
254+
255+
// Try and run GC because we're blocked and sending a block message
256+
// to the CD. This will try and free any memory the actor has in its
257+
// heap that wouldn't get freed otherwise until the actor is
258+
// destroyed or happens to receive more work via application messages
259+
// that eventually trigger a GC which may not happen for a long time
260+
// (or ever). Do this BEFORE sending the message or else we might be
261+
// GCing while the CD destroys us.
262+
pony_triggergc(ctx);
263+
try_gc(ctx, actor);
264+
265+
// We're blocked, send block message.
255266
set_internal_flag(actor, FLAG_BLOCKED_SENT);
256267
set_internal_flag(actor, FLAG_CD_CONTACTED);
257268
ponyint_cycle_block(actor, &actor->gc);
258-
259-
// Trigger garbage collection. GC will get run next time `try_gc` is called
260-
// which should happen once all messages get processed in the messageq
261-
// at the time `pony_actor_run` was called if not earlier
262-
// when an app message is processed
263-
pony_triggergc(ctx);
264269
}
265270

266271
static bool handle_message(pony_ctx_t* ctx, pony_actor_t* actor,
@@ -644,20 +649,12 @@ bool ponyint_actor_run(pony_ctx_t* ctx, pony_actor_t* actor, bool polling)
644649
)
645650
{
646651
// The cycle detector (CD) doesn't know we exist so it won't try
647-
// and reach out to us even though we're blocked, so send block message //// and set flag that the CD knows we exist now so that when we block
652+
// and reach out to us even though we're blocked, so send block message
653+
// and set flag that the CD knows we exist now so that when we block
648654
// in the future we will wait for the CD to reach out and ask
649655
// if we're blocked or not.
650656
// But, only if gc.rc > 0 because if gc.rc == 0 we are a zombie.
651657
send_block(ctx, actor);
652-
653-
// Try and run GC because we're blocked and sending a block message
654-
// to the CD and we're past the normal point at which `try_gc` is
655-
// called as part of this function. This will try and free any
656-
// memory the actor has in its heap that wouldn't get freed otherwise
657-
// until the actor is destroyed or happens to receive more work via
658-
// application messages that eventually trigger a GC which may not
659-
// happen for a long time (or ever).
660-
try_gc(ctx, actor);
661658
}
662659

663660
}

0 commit comments

Comments
 (0)