Skip to content

Commit 25ba283

Browse files
committed
Merge pull request #1755 from petermm/sup_which_children
Add which_children/1 to supervisor.erl These changes are made under both the "Apache 2.0" and the "GNU Lesser General Public License 2.1 or later" license terms (dual license). SPDX-License-Identifier: Apache-2.0 OR LGPL-2.1-or-later
2 parents 9a6bf85 + e566902 commit 25ba283

File tree

3 files changed

+65
-6
lines changed

3 files changed

+65
-6
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
5252
- Added `erlang:module_loaded/1`
5353
- Added `binary:replace/3`, `binary:replace/4`
5454
- Added `binary:match/2` and `binary:match/3`
55+
- Added `supervisor:which_children/1`
5556

5657
### Changed
5758

libs/estdlib/src/supervisor.erl

Lines changed: 33 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,8 @@
2828
start_child/2,
2929
terminate_child/2,
3030
restart_child/2,
31-
delete_child/2
31+
delete_child/2,
32+
which_children/1
3233
]).
3334

3435
-export([
@@ -86,7 +87,8 @@
8687
start :: {module(), atom(), [any()] | undefined},
8788
restart :: restart(),
8889
shutdown :: shutdown(),
89-
type :: child_type
90+
type :: child_type,
91+
modules = [] :: [module()] | dynamic
9092
}).
9193
-record(state, {restart_strategy :: strategy(), children = [] :: [#child{}]}).
9294

@@ -107,6 +109,9 @@ restart_child(Supervisor, ChildId) ->
107109
delete_child(Supervisor, ChildId) ->
108110
gen_server:call(Supervisor, {delete_child, ChildId}).
109111

112+
which_children(Supervisor) ->
113+
gen_server:call(Supervisor, which_children).
114+
110115
init({Mod, Args}) ->
111116
erlang:process_flag(trap_exit, true),
112117
case Mod:init(Args) of
@@ -123,13 +128,14 @@ init({Mod, Args}) ->
123128
end.
124129

125130
-spec child_spec_to_record(child_spec()) -> #child{}.
126-
child_spec_to_record({ChildId, MFA, Restart, Shutdown, Type, _Modules}) ->
131+
child_spec_to_record({ChildId, MFA, Restart, Shutdown, Type, Modules}) ->
127132
#child{
128133
id = ChildId,
129134
start = MFA,
130135
restart = Restart,
131136
shutdown = Shutdown,
132-
type = Type
137+
type = Type,
138+
modules = Modules
133139
};
134140
child_spec_to_record(#{id := ChildId, start := MFA} = ChildMap) ->
135141
Restart = maps:get(restart, ChildMap, permanent),
@@ -142,12 +148,21 @@ child_spec_to_record(#{id := ChildId, start := MFA} = ChildMap) ->
142148
supervisor -> infinity
143149
end
144150
),
151+
Modules = maps:get(
152+
modules,
153+
ChildMap,
154+
case MFA of
155+
{M, _, _} -> [M];
156+
_ -> []
157+
end
158+
),
145159
#child{
146160
id = ChildId,
147161
start = MFA,
148162
restart = Restart,
149163
shutdown = Shutdown,
150-
type = Type
164+
type = Type,
165+
modules = Modules
151166
}.
152167

153168
init_state([ChildSpec | T], State) ->
@@ -262,7 +277,10 @@ handle_call({delete_child, ID}, _From, #state{children = Children} = State) ->
262277
{reply, {error, running}, State};
263278
false ->
264279
{reply, {error, not_found}, State}
265-
end.
280+
end;
281+
handle_call(which_children, _From, #state{children = Children} = State) ->
282+
ChildrenInfo = lists:map(fun child_to_info/1, Children),
283+
{reply, ChildrenInfo, State}.
266284

267285
handle_cast(_Msg, State) ->
268286
{noreply, State}.
@@ -337,6 +355,15 @@ try_start(#child{start = {M, F, Args}} = Record) ->
337355
{error, {{'EXIT', Error}, Record}}
338356
end.
339357

358+
child_to_info(#child{id = Id, pid = Pid, type = Type, modules = Modules}) ->
359+
Child =
360+
case Pid of
361+
undefined -> undefined;
362+
{restarting, _} -> restarting;
363+
_ when is_pid(Pid) -> Pid
364+
end,
365+
{Id, Child, Type, Modules}.
366+
340367
do_terminate(#child{pid = Pid, shutdown = brutal_kill}) ->
341368
exit(Pid, kill);
342369
do_terminate(#child{pid = Pid, shutdown = infinity}) ->

tests/libs/estdlib/test_supervisor.erl

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ test() ->
3333
ok = test_supervisor_order(),
3434
ok = test_terminate_delete_child(),
3535
ok = test_terminate_timeout(),
36+
ok = test_which_children(),
3637
ok.
3738

3839
test_basic_supervisor() ->
@@ -259,3 +260,33 @@ test_supervisor_order() ->
259260
unlink(SupPid),
260261
exit(SupPid, shutdown),
261262
ok.
263+
264+
test_which_children() ->
265+
% Test with no children
266+
{ok, SupPid} = supervisor:start_link(?MODULE, {test_no_child, self()}),
267+
[] = supervisor:which_children(SupPid),
268+
269+
% Add a child and test
270+
{ok, _ChildPid} = supervisor:start_child(SupPid, #{
271+
id => test_child,
272+
start => {ping_pong_server, start_link, [self()]},
273+
restart => permanent,
274+
shutdown => 5000,
275+
type => worker
276+
}),
277+
278+
% Check which_children returns the child info
279+
[{test_child, ChildPid, worker, [ping_pong_server]}] = supervisor:which_children(SupPid),
280+
true = is_pid(ChildPid),
281+
282+
% Terminate the child and check it shows as undefined
283+
ok = supervisor:terminate_child(SupPid, test_child),
284+
[{test_child, undefined, worker, [ping_pong_server]}] = supervisor:which_children(SupPid),
285+
286+
% Delete the child and check empty list
287+
ok = supervisor:delete_child(SupPid, test_child),
288+
[] = supervisor:which_children(SupPid),
289+
290+
unlink(SupPid),
291+
exit(SupPid, shutdown),
292+
ok.

0 commit comments

Comments
 (0)