diff --git a/erts/emulator/beam/atom.names b/erts/emulator/beam/atom.names index b017300f4a5e..c264082e7561 100644 --- a/erts/emulator/beam/atom.names +++ b/erts/emulator/beam/atom.names @@ -578,6 +578,8 @@ atom processes atom processes_used atom process_count atom process_display +atom DollarProcessLabel='$process_label' +atom process_limit atom process_limit atom process_dump atom procs diff --git a/erts/emulator/beam/erl_bif_info.c b/erts/emulator/beam/erl_bif_info.c index f9f366523cc1..13169e56b9e3 100644 --- a/erts/emulator/beam/erl_bif_info.c +++ b/erts/emulator/beam/erl_bif_info.c @@ -782,6 +782,7 @@ collect_one_suspend_monitor(ErtsMonitor *mon, void *vsmicp, Sint reds) #define ERTS_PI_IX_PARENT 36 #define ERTS_PI_IX_ASYNC_DIST 37 #define ERTS_PI_IX_DICTIONARY_LOOKUP 38 +#define ERTS_PI_IX_LABEL 39 #define ERTS_PI_UNRESERVE(RS, SZ) \ (ASSERT((RS) >= (SZ)), (RS) -= (SZ)) @@ -834,6 +835,7 @@ static ErtsProcessInfoArgs pi_args[] = { {am_parent, 0, 0, ERTS_PROC_LOCK_MAIN}, {am_async_dist, 0, 0, ERTS_PROC_LOCK_MAIN}, {am_dictionary, 3, ERTS_PI_FLAG_FORCE_SIG_SEND|ERTS_PI_FLAG_KEY_TUPLE2, ERTS_PROC_LOCK_MAIN}, + {am_label, 0, ERTS_PI_FLAG_FORCE_SIG_SEND, ERTS_PROC_LOCK_MAIN}, }; #define ERTS_PI_ARGS ((int) (sizeof(pi_args)/sizeof(pi_args[0]))) @@ -966,6 +968,8 @@ pi_arg2ix(Eterm arg, Eterm *extrap) return ERTS_PI_IX_PARENT; case am_async_dist: return ERTS_PI_IX_ASYNC_DIST; + case am_label: + return ERTS_PI_IX_LABEL; default: if (is_tuple_arity(arg, 2)) { Eterm *tpl = tuple_val(arg); @@ -2279,6 +2283,22 @@ process_info_aux(Process *c_p, break; } + case ERTS_PI_IX_LABEL: { + Uint sz; + + res = erts_pd_hash_get(rp, am_DollarProcessLabel); + sz = (!(flags & ERTS_PI_FLAG_REQUEST_FOR_OTHER) || is_immed(res) + ? 0 + : size_object(res)); + + hp = erts_produce_heap(hfact, sz, reserve_size); + + if (sz) + res = copy_struct(res, sz, &hp, hfact->off_heap); + + break; + } + default: return THE_NON_VALUE; /* will produce badarg */ diff --git a/erts/emulator/test/process_SUITE.erl b/erts/emulator/test/process_SUITE.erl index c8b86e4e740b..9680eb5836fd 100644 --- a/erts/emulator/test/process_SUITE.erl +++ b/erts/emulator/test/process_SUITE.erl @@ -55,6 +55,7 @@ process_info_self_msgq_len_more/1, process_info_msgq_len_no_very_long_delay/1, process_info_dict_lookup/1, + process_info_label/1, bump_reductions/1, low_prio/1, binary_owner/1, yield/1, yield2/1, otp_4725/1, dist_unlink_ack_exit_leak/1, bad_register/1, garbage_collect/1, otp_6237/1, @@ -182,7 +183,8 @@ groups() -> process_info_self_msgq_len_messages, process_info_self_msgq_len_more, process_info_msgq_len_no_very_long_delay, - process_info_dict_lookup]}, + process_info_dict_lookup, + process_info_label]}, {otp_7738, [], [otp_7738_waiting, otp_7738_suspended, otp_7738_resume]}, @@ -1728,6 +1730,25 @@ process_info_dict_lookup(Config) when is_list(Config) -> false = is_process_alive(Pid), ok. +process_info_label(Config) when is_list(Config) -> + Pid = spawn_link(fun proc_dict_helper/0), + LabelKey = '$process_label', + Ref = make_ref(), + Tuple = {make_ref(), erlang:monotonic_time()}, + + undefined = pdh(Pid, put, [LabelKey, Tuple]), + erlang:garbage_collect(Pid), + + {label,Tuple} = process_info(Pid, label), + Self = self(), + [{label,Tuple},{registered_name,[]},{links,[Self]}] = + process_info(Pid, [label,registered_name,links]), + + put(LabelKey, Ref), + {label,Ref} = process_info(self(), label), + + ok. + pdh(Pid, AsyncOp, Args) when AsyncOp == put_async; AsyncOp == erase_async -> Pid ! {AsyncOp, Args}, diff --git a/erts/preloaded/ebin/erlang.beam b/erts/preloaded/ebin/erlang.beam index db3161848848..aed9bed68383 100644 Binary files a/erts/preloaded/ebin/erlang.beam and b/erts/preloaded/ebin/erlang.beam differ diff --git a/erts/preloaded/src/erlang.erl b/erts/preloaded/src/erlang.erl index 6357cbeea608..3c950c0a2f53 100644 --- a/erts/preloaded/src/erlang.erl +++ b/erts/preloaded/src/erlang.erl @@ -7663,6 +7663,7 @@ process_flag(_Flag, _Value) -> heap_size | initial_call | links | + label | last_calls | memory | message_queue_len | @@ -7707,6 +7708,7 @@ process_flag(_Flag, _Value) -> {heap_size, Size :: non_neg_integer()} | {initial_call, mfa()} | {links, PidsAndPorts :: [pid() | port()]} | + {label, term()} | {last_calls, false | (Calls :: [mfa()])} | {memory, Size :: non_neg_integer()} | {message_queue_len, MessageQueueLen :: non_neg_integer()} | @@ -7842,6 +7844,11 @@ Valid `InfoTuple`s with corresponding `Item`s: - **`{links, PidsAndPorts}`** - `PidsAndPorts` is a list of process identifiers and port identifiers, with processes or ports to which the process has a link. +- **`{label, Label}`** - + `Label` is the label for the process. See `proc_lib:get_label/1`. + + Since: OTP 27.2 + - **`{last_calls, false|Calls}`** - The value is `false` if call saving is not active for the process (see `process_flag/3`). If call saving is active, a list is returned, in which the last element is the most recent called.