Skip to content

Commit f8c9118

Browse files
Merge pull request #10241 from jcpetruzza/fix_suspend_internal_error
Fix suspend_process() issue on processes in dirty schedulers
2 parents 2216e2f + 410680d commit f8c9118

File tree

2 files changed

+99
-4
lines changed

2 files changed

+99
-4
lines changed

erts/emulator/beam/erl_proc_sig_queue.c

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5489,6 +5489,7 @@ sync_suspend_reply(Process *c_p, ErtsMessage *mp, erts_aint32_t state)
54895489
*/
54905490
Process *rp;
54915491
ErtsSyncSuspendRequest *ssusp;
5492+
int is_managed;
54925493

54935494
ssusp = (ErtsSyncSuspendRequest *) (char *) (&mp->hfrag.mem[0]
54945495
+ mp->hfrag.used_size);
@@ -5508,7 +5509,10 @@ sync_suspend_reply(Process *c_p, ErtsMessage *mp, erts_aint32_t state)
55085509
mp->data.attached = ERTS_MSG_COMBINED_HFRAG;
55095510
mp->next = NULL;
55105511

5511-
rp = erts_proc_lookup(ssusp->requester);
5512+
is_managed = erts_thr_progress_is_managed_thread();
5513+
rp = (is_managed
5514+
? erts_proc_lookup(ssusp->requester)
5515+
: erts_proc_lookup_inc_refc(ssusp->requester));
55125516
if (!rp)
55135517
erts_cleanup_messages(mp);
55145518
else {
@@ -5527,6 +5531,8 @@ sync_suspend_reply(Process *c_p, ErtsMessage *mp, erts_aint32_t state)
55275531
}
55285532
ERL_MESSAGE_TOKEN(mp) = am_undefined;
55295533
erts_queue_proc_message(c_p, rp, 0, mp, ssusp->message);
5534+
if (!is_managed)
5535+
erts_proc_dec_refc(rp);
55305536
}
55315537
}
55325538

@@ -5667,6 +5673,8 @@ erts_proc_sig_handle_pending_suspend(Process *c_p)
56675673
msp = next_msp;
56685674
}
56695675

5676+
state = erts_atomic32_read_nob(&c_p->state);
5677+
56705678
sync = psusp->sync;
56715679

56725680
while (sync) {

erts/emulator/test/dirty_bif_SUITE.erl

Lines changed: 90 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,8 @@
4141
dirty_process_register/1,
4242
dirty_process_trace/1,
4343
code_purge/1,
44-
otp_15688/1]).
44+
otp_15688/1,
45+
suspend_process/1]).
4546

4647
suite() -> [{ct_hooks,[ts_install_cth]}].
4748

@@ -68,7 +69,8 @@ all() ->
6869
dirty_process_register,
6970
dirty_process_trace,
7071
code_purge,
71-
otp_15688].
72+
otp_15688,
73+
suspend_process].
7274

7375
init_per_suite(Config) ->
7476
case erlang:system_info(dirty_cpu_schedulers) of
@@ -541,7 +543,92 @@ otp_15688(Config) when is_list(Config) ->
541543
exit(See, kill),
542544
ct:fail({suspendee_stuck, PI})
543545
end.
544-
546+
547+
suspend_process(Config) when is_list(Config) ->
548+
Go = make_ref(),
549+
AS = make_ref(),
550+
Tester = self(),
551+
P = spawn_link(fun () ->
552+
receive {Go, 1} -> ok end,
553+
Tester ! {Go, 2},
554+
erts_debug:dirty_io(wait, 500),
555+
receive {Go, 3}-> ok end,
556+
Tester ! {Go, 4},
557+
erts_debug:dirty_io(wait, 500),
558+
receive {Go, 5} -> ok end,
559+
Tester ! {Go, 6},
560+
erts_debug:dirty_cpu(wait, 500),
561+
receive {Go, 7} -> ok end,
562+
Tester ! {Go, 8},
563+
erts_debug:dirty_cpu(wait, 500)
564+
end),
565+
566+
%% Sync DIO
567+
{status, Status1} = erlang:process_info(P, status),
568+
false = Status1 == suspended,
569+
570+
P ! {Go, 1},
571+
receive {Go, 2} -> ok end,
572+
erlang:yield(),
573+
true = erlang:suspend_process(P),
574+
575+
{status, Status2} = erlang:process_info(P, status),
576+
true = Status2 == suspended,
577+
578+
true = erlang:resume_process(P),
579+
580+
%% Async DIO
581+
{status, Status3} = erlang:process_info(P, status),
582+
false = Status3 == suspended,
583+
584+
P ! {Go, 3},
585+
receive {Go, 4} -> ok end,
586+
erlang:yield(),
587+
588+
true = erlang:suspend_process(P, [{asynchronous, AS}]),
589+
receive {AS, What1} -> suspended = What1 end,
590+
591+
{status, Status4} = erlang:process_info(P, status),
592+
true = Status4 == suspended,
593+
594+
true = erlang:resume_process(P),
595+
596+
%% Sync DCPU
597+
{status, Status5} = erlang:process_info(P, status),
598+
false = Status5 == suspended,
599+
600+
P ! {Go, 5},
601+
receive {Go, 6} -> ok end,
602+
erlang:yield(),
603+
604+
true = erlang:suspend_process(P),
605+
606+
{status, Status6} = erlang:process_info(P, status),
607+
true = Status6 == suspended,
608+
609+
true = erlang:resume_process(P),
610+
611+
%% Async DCPU
612+
{status, Status7} = erlang:process_info(P, status),
613+
false = Status7 == suspended,
614+
615+
P ! {Go, 7},
616+
receive {Go, 8} -> ok end,
617+
erlang:yield(),
618+
619+
true = erlang:suspend_process(P, [{asynchronous, AS}]),
620+
receive {AS, What2} -> suspended = What2 end,
621+
622+
{status, Status8} = erlang:process_info(P, status),
623+
true = Status8 == suspended,
624+
625+
true = erlang:resume_process(P),
626+
627+
unlink(P),
628+
exit(P, kill),
629+
false = is_process_alive(P),
630+
631+
ok.
545632

546633
%%
547634
%% Internal...

0 commit comments

Comments
 (0)