Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Keep supervisor children linked during shutdown #5201

Merged

Conversation

Maria-12648430
Copy link
Contributor

This PR was prompted by this thread on the Erlang Questions ML, concerning unexpected noproc exit reasons due to a race condition when a supervisor child self-terminates and is at the same time terminated via supervisor:terminate_child/2. In the course of the discussion, it was discovered that there exists a condition where a child could become orphaned when its supervisor dies at a critical moment.

In a nutshell, in the current implementation, the procedure of shutting down a child is as follows:

  1. set a monitor on the child
  2. unlink the child
  3. try to flush out a possible 'EXIT' message in case the child just died by itself
  4. send a shutdown exit signal to the child and wait for a 'DOWN' message
  5. send a kill signal to the child if it does not shut down in time and wait for the 'DOWN' message

However, if the supervisor dies between (2) and (4), the child will be left running, unaware even that it has become an orphan.

This PR changes the procedure as follows:

  1. set a monitor on the child
  2. send a shutdown exit signal to the child and wait for a 'DOWN' message, then unlink it and flush out the possible 'EXIT' message
  3. send a kill signal to the child if it does not shut down in time and wait for the 'DOWN' message, then unlink it and flush out the possible 'EXIT' message

This way, the child remains linked to the supervisor until it is definitely dead.
Flushing out the 'EXIT' messages implicitly serves as a way to retrieve the child's exit reason (the 'DOWN' message might reach the child only after it has died earlier, ie too late, resulting in the noproc that prompted the initial post on the aforementioned thread). This is a best-effort approach (which comes for free), if the child unlinked itself from the supervisor ("naughty child"), there will be not 'EXIT' message.

Additionally, this PR handles some exit reasons as normal (ie, not logging them as errors) which would be reported by the current implementation simply because the child exited at the wrong moment.

@rickard-green rickard-green added the team:VM Assigned to OTP team VM label Sep 15, 2021
@rickard-green rickard-green self-assigned this Sep 15, 2021
@rickard-green rickard-green added the testing currently being tested, tag is used by OTP internal CI label Sep 15, 2021
case unlink_flush(Pid, Reason0) of
shutdown ->
ok;
{shutdown, _} ->
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As {shutdown, Reason} is a way for the child process to terminate itself normally (gracefully but with a trail as to why). Maybe it should also have a guard not (is_pernmanent(Child)). I must confess I actually have not used permanent children. But that would be backwards compatible and it seems to make sense that if we do not accept normal as a shutdown reason {shutdown, Reason} should not be accepted either and only the shutdown initiated by the supervisor should be considered a non-fault.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Makes sense I think.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changed as suggested in last commit.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

Copy link
Contributor

@rickard-green rickard-green left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good!

However, there is poor coverage in some cases in the tests, so test-case improvements would be welcome. The brutal_kill scenario for dynamic workers is not tested at all. Children terminating simultaneously by them selves are also poorly cover. This can, however, be hard to trigger.

921 |   | shutdown(#child{pid=Pid, shutdown=brutal_kill} = Child) ->
-- | -- | --
922 | 11 | Mon = monitor(process, Pid),
923 | 11 | exit(Pid, kill),
924 | 11 | receive
925 |   | {'DOWN', Mon, process, Pid, Reason0} ->
926 | 11 | case unlink_flush(Pid, Reason0) of
927 |   | killed ->
928 | 11 | ok;
929 |   | normal when not (?is_permanent(Child)) ->
930 | :-( | ok;
931 |   | Reason ->
932 | :-( | {error, Reason}
933 |   | end
934 |   | end;
935 |   | shutdown(#child{pid=Pid, shutdown=Time} = Child) ->
936 | 112083 | Mon = monitor(process, Pid),
937 | 112083 | exit(Pid, shutdown),
938 | 112083 | receive
939 |   | {'DOWN', Mon, process, Pid, Reason0} ->
940 | 112080 | case unlink_flush(Pid, Reason0) of
941 |   | shutdown ->
942 | 112080 | ok;
943 |   | {shutdown, _} ->
944 | :-( | ok;
945 |   | normal when not (?is_permanent(Child)) ->
946 | :-( | ok;
947 |   | Reason ->
948 | :-( | {error, Reason}
949 |   | end
950 |   | after Time ->
951 | 1 | exit(Pid, kill),
952 | 1 | receive
953 |   | {'DOWN', Mon, process, Pid, Reason0} ->
954 | 1 | case unlink_flush(Pid, Reason0) of
955 |   | shutdown ->
956 | :-( | ok;
957 |   | {shutdown, _} ->
958 | :-( | ok;
959 |   | normal when not (?is_permanent(Child)) ->
960 | :-( | ok;
961 |   | Reason ->
962 | 1 | {error, Reason}
963 |   | end
964 |   | end
965 |   | end.
966 |   |  
967 |   | unlink_flush(Pid, DefaultReason) ->
968 | 112405 | unlink(Pid),
969 | 112405 | receive
970 |   | {'EXIT', Pid, Reason} ->
971 | 112404 | Reason
972 |   | after 0 ->
973 | 1 | DefaultReason
974 |   | end.
975 |   |  
976 |   | %%-----------------------------------------------------------------
977 |   | %% Func: terminate_dynamic_children/1
978 |   | %% Args: State
979 |   | %% Returns: ok
980 |   | %%
981 |   | %% Shutdown all dynamic children. This happens when the supervisor is
982 |   | %% stopped. Because the supervisor can have millions of dynamic children, we
983 |   | %% can have a significative overhead here.
984 |   | %%-----------------------------------------------------------------
985 |   | terminate_dynamic_children(State) ->
986 | 22 | Child = get_dynamic_child(State),
987 | 22 | Pids = dyn_fold(
988 |   | fun
989 |   | (P, Acc) when is_pid(P) ->
990 | 313 | Mon = monitor(process, P),
991 | 313 | case Child#child.shutdown of
992 | :-( | brutal_kill -> exit(P, kill);
993 | 313 | _ -> exit(P, shutdown)
994 |   | end,
995 | 313 | Acc#{{P, Mon} => true};
996 |   | (?restarting(_), Acc) ->
997 | 1 | Acc
998 |   | end,
999 |   | #{},
1000 |   | State
1001 |   | ),
1002 | 22 | TRef = case Child#child.shutdown of
1003 |   | brutal_kill ->
1004 | 2 | undefined;
1005 |   | infinity ->
1006 | 1 | undefined;
1007 |   | Time ->
1008 | 19 | erlang:start_timer(Time, self(), kill)
1009 |   | end,
1010 | 22 | Sz = maps:size(Pids),
1011 | 22 | EStack = wait_dynamic_children(Child, Pids, Sz, TRef, #{}),
1012 |   | %% Unroll stacked errors and report them
1013 | 22 | maps:foreach(fun(Reason, Ls) ->
1014 | 1 | ?report_error(shutdown_error, Reason,
1015 | :-( | Child#child{pid=Ls}, State#state.name)
1016 |   | end, EStack).
1017 |   |  
1018 |   | wait_dynamic_children(_Child, _Pids, 0, undefined, EStack) ->
1019 | 4 | EStack;
1020 |   | wait_dynamic_children(_Child, _Pids, 0, TRef, EStack) ->
1021 |   | %% If the timer has expired before its cancellation, we must empty the
1022 |   | %% mail-box of the 'timeout'-message.
1023 | 18 | _ = erlang:cancel_timer(TRef),
1024 | 18 | receive
1025 |   | {timeout, TRef, kill} ->
1026 | :-( | EStack
1027 |   | after 0 ->
1028 | 18 | EStack
1029 |   | end;
1030 |   | wait_dynamic_children(#child{shutdown=brutal_kill} = Child, Pids, Sz,
1031 |   | TRef, EStack) ->
1032 | :-( | receive
1033 |   | {'DOWN', Mon, process, Pid, Reason0}
1034 |   | when is_map_key({Pid, Mon}, Pids) ->
1035 | :-( | case unlink_flush(Pid, Reason0) of
1036 |   | killed ->
1037 | :-( | wait_dynamic_children(Child, maps:remove({Pid, Mon}, Pids),
1038 |   | Sz-1, TRef, EStack);
1039 |   |  
1040 |   | normal when not (?is_permanent(Child)) ->
1041 | :-( | wait_dynamic_children(Child, maps:remove({Pid, Mon}, Pids),
1042 |   | Sz-1, TRef, EStack);
1043 |   | Reason ->
1044 | :-( | wait_dynamic_children(Child, maps:remove({Pid, Mon}, Pids),
1045 |   | Sz-1, TRef, maps_prepend(Reason, Pid,
1046 |   | EStack))
1047 |   | end
1048 |   | end;
1049 |   | wait_dynamic_children(Child, Pids, Sz, TRef, EStack) ->
1050 | 314 | receive
1051 |   | {'DOWN', Mon, process, Pid, Reason0}
1052 |   | when is_map_key({Pid, Mon}, Pids) ->
1053 | 313 | case unlink_flush(Pid, Reason0) of
1054 |   | shutdown ->
1055 | 312 | wait_dynamic_children(Child, maps:remove({Pid, Mon}, Pids),
1056 |   | Sz-1, TRef, EStack);
1057 |   |  
1058 |   | {shutdown, _} ->
1059 | :-( | wait_dynamic_children(Child, maps:remove({Pid, Mon}, Pids),
1060 |   | Sz-1, TRef, EStack);
1061 |   |  
1062 |   | normal when not (?is_permanent(Child)) ->
1063 | :-( | wait_dynamic_children(Child, maps:remove({Pid, Mon}, Pids),
1064 |   | Sz-1, TRef, EStack);
1065 |   |  
1066 |   | Reason ->
1067 | 1 | wait_dynamic_children(Child, maps:remove({Pid, Mon}, Pids),
1068 |   | Sz-1, TRef, maps_prepend(Reason, Pid,
1069 |   | EStack))
1070 |   | end;
1071 |   |  
1072 |   | {timeout, TRef, kill} ->
1073 | 1 | maps:foreach(fun({P, _}, _) -> exit(P, kill) end, Pids),
1074 | 1 | wait_dynamic_children(Child, Pids, Sz, undefined, EStack)
1075 |   | end.
1076 |   |  
1077 |   | maps_prepend(Key, Value, Map) ->
1078 | 1 | case maps:find(Key, Map) of
1079 |   | {ok, Values} ->
1080 | :-( | maps:put(Key, [Value\|Values], Map);
1081 |   | error ->
1082 | 1 | maps:put(Key, [Value], Map)
1083 |   | end.
1084 |   |  


@rickard-green rickard-green added testing currently being tested, tag is used by OTP internal CI and removed testing currently being tested, tag is used by OTP internal CI labels Sep 17, 2021
@Maria-12648430
Copy link
Contributor Author

@rickard-green ok, I'll see what @juhlig I can do next week 😁

@juhlig
Copy link
Contributor

juhlig commented Sep 17, 2021

@Maria-12648430 don't drag me into this >_< sure, delighted to be of assistance ^^;;;

@juhlig
Copy link
Contributor

juhlig commented Sep 21, 2021

@rickard-green @Maria-12648430 I added some tests that cover the shutdown process, except for those cases in the brutal_kill and kill-after-timeout scenarios. What do you think?

@Maria-12648430
Copy link
Contributor Author

Thanks 🤗 I'll take a closer look later. From what I see, you are using a child that takes some time to shut down to delay the supervisor and let other children exit by themselves?

@juhlig
Copy link
Contributor

juhlig commented Sep 21, 2021

That's the idea, yes :)

@juhlig
Copy link
Contributor

juhlig commented Sep 21, 2021

That doesn't work for simple_one_for_one supervisors, though, they shut down all their children in parallel. So... :\

@rickard-green rickard-green added testing currently being tested, tag is used by OTP internal CI and removed testing currently being tested, tag is used by OTP internal CI labels Sep 21, 2021
@HansN
Copy link
Contributor

HansN commented Sep 22, 2021

I've tested this PR on SSH's tests after a tips by @IngelaAndin.

Usually there are about 30 SUPERVISOR REPORTs due to a harmless hazard in the SSH supervisor tree. The sequence closing down the test cases triggers that hazard sometimes.

With this PR all those reports vanish - I've tested three times! What about rebasing this PR on top of maint? It might also fix a couple of hard, non reproducible nor replicable issue reports in SSH too.

Comments from the asignee @rickard-green (or anyone else of course) ?

@rickard-green
Copy link
Contributor

@Maria-12648430 @juhlig The test coverage looks much better now!

@HansN wrote:

With this PR all those reports vanish - I've tested three times! What about rebasing this PR on top of maint?

Rebasing on top of the maint-24 branch would be even better. Then we have the option to release this in an emergency patch on OTP 24 which I think we probably should.

@Maria-12648430
Copy link
Contributor Author

@Maria-12648430 @juhlig The test coverage looks much better now!

Great 😄

Rebasing on top of the maint-24 branch would be even better. Then we have the option to release this in an emergency patch on OTP 24 which I think we probably should.

Ok. Everybody (involved) agrees?

@rickard-green
Copy link
Contributor

Rebasing on top of the maint-24 branch would be even better. Then we have the option to release this in an emergency patch on OTP 24 which I think we probably should.

Ok. Everybody (involved) agrees?

From a patch perspective it is always better to base the fix on an as early normal version (green versions in the version tree) as possible, since it then can be merged forward to all later versions. If based on top of maint-24 we can later determine to release it on maint-24, maint or master without any changes. If based on maint, it cannot be released on maint-24 without backporting it via a cherry pick. Backporting it this way is of course possible, but the git history looks ugly and it is harder to track the introduction of changes compared to when a change is introduced in a set of commits that then only are merged forward.

Note that you cannot base it on the top of maint-23 or earlier maint-XY branches, since these bases cannot be safely merged into maint-24 without the risk of pulling in unrelated stuff (only green versions in the versions tree are safe bases from this perspective). Basing it on the tag OTP-22.3.4 would make it possible to release the fix as patches on maint-22 and maint-23 as well without backporting.

It is however possible to get into some trouble if you base a fix on a version that is too early, with merge conflicts due to rewrites in the same area and functionality not introduced yet that you need, so you don't want to base it on a too early version.

You won't get into any such trouble using the top of maint-24 as base compared to basing it on top of maint for this fix though (especially since we just released on maint, so maint and maint-24 are very close to each other now). You might get into such trouble using earlier versions though, since there have been changes in supervisor lately. Hopefully those changes in supervisor were made on a previous top of maint otherwise a rebase to maint-24 (and maint) might not be that easy. If the rebase becomes too messy you can leave it on master. It is always possible for us to backport it via a cherry pick in order to release it as a patch.

@IngelaAndin
Copy link
Contributor

It should easily rebase on maint as @HansN already tried that. I guess normally we expect our Open Source user to base things on maint or master. But as you say Rickard it can be interesting to actually patch this earlier than OTP-24.3 and so maint-24 is then a good idea. I guess we will have to take care of the merges locally,not using the merge button here though!

@Maria-12648430
Copy link
Contributor Author

@IngelaAndin @rickard-green Okaaay... so what shall I do, and how? 😅 TBH, I only tried that once before and probably did it wrong since I had to sort out conflicts afterwards, so... is changing the base branch for this PR here (ie via edit -> "base: master" -> "base: maint-24") enough?

@IngelaAndin
Copy link
Contributor

I would stand on your branch and do git rebase ---onto maint-24 HEAD~N where N are the number of commits that you have. Then it will take maint-24 and try to apply your commits with maint-24 as the base. The github thing will only work under some circumstances when moving something forward. You can always save a copy of your branch somewhere as backup if you feel nervous, although git has ways to restore mistakes even if you do not.

Children were monitored and unlinked before sending the shutdown exit signal.
If the supervisor dies between the unlinking and sending the exit signal, the
child becomes an orphan.
For similar reasons, erratic error messages would occur in logs when a child
exited by itself while the supervisor tries to shut it down.

The changes in this commit keep children linked until they have exited, and
treat exit reasons as normal which may occur when a child exits by itself
while being shut down by the supervisor.

Co-authored-by: Jan Uhlig <juhlig@hnc-agency.org>
@Maria-12648430
Copy link
Contributor Author

Ok, thanks for the pointers @IngelaAndin, worked like a charm 😄.
So I rebased on maint-24, squashed and augmented the commit message. Now let's see.

(Btw, this PR still says "Maria-12648430 wants to merge 1 commit into erlang:master from Maria-12648430:supervisor_unlink_child_late" up there ☝️ Don't know if it matters, just pointing it out)

@HansN
Copy link
Contributor

HansN commented Sep 23, 2021

@Maria-12648430 I fetch:ed from github, and your branch is now based on maint-24 ( for the moment = OPT-24.1).
I also see in this PR window that the merge is supposed to be with erlang:master (which is another thing than "based on"). However, I also have en edit button right of the titel on top of the window. If I click that one, I seem to be able to change the branch to merge to. Being a bit formal, I didn't do that since I'm not the asignee :)

@Maria-12648430
Copy link
Contributor Author

Being a bit formal, I didn't do that since I'm not the asignee :)

Let's leave that to @rickard-green then 😉 Or do the merge locally (vs the merge button), as @IngelaAndin suggested.

@IngelaAndin
Copy link
Contributor

IngelaAndin commented Sep 23, 2021

@Maria-12648430 @HansN @rickard-green I think we actually now should be able to change branch to maint with the edit as it now based on maint-24 and hence can cleanly be merged froward. I just realized that should enable us to use the merge button for the PR too and then reuse the branch in our patch script. (That is we want it to say maint up there and not maint-24 but the branch can be based on maint-24).

@rickard-green rickard-green added testing currently being tested, tag is used by OTP internal CI and removed testing currently being tested, tag is used by OTP internal CI labels Sep 23, 2021
@rickard-green
Copy link
Contributor

rickard-green commented Sep 23, 2021

Clarification: By messy merges I mean lots of merge conflicts when merging forward to maint and master

@HansN HansN added testing currently being tested, tag is used by OTP internal CI and removed testing currently being tested, tag is used by OTP internal CI labels Sep 23, 2021
@Maria-12648430
Copy link
Contributor Author

So, how are things here? Any news from testing? @HansN @rickard-green

@rickard-green
Copy link
Contributor

I haven't looked closely at testing of this (been fully occupied with other bugfixes), but I haven't seen any obvious issues. @HansN has maybe paid closer attention to this? Unless I find something worrying I will include these changes in the next patch which probably will be released later this week. One thing left to do is to write a release note, so if you have a suggestion for that it would be nice :-)

@Maria-12648430
Copy link
Contributor Author

Maria-12648430 commented Sep 28, 2021

One thing left to do is to write a release note, so if you have a suggestion for that it would be nice :-)

Ummm... not sure 😅 FWIW, this is what I put as commit message, maybe you can distill something from that? I can't think of anything better that describes both the problem and the solution...

Keep supervisor children linked during shutdown

Children were monitored and unlinked before sending the shutdown exit signal.
If the supervisor dies between the unlinking and sending the exit signal, the
child becomes an orphan.
For similar reasons, erratic error messages would occur in logs when a child
exited by itself while the supervisor tries to shut it down.

The changes in this commit keep children linked until they have exited, and
treat exit reasons as normal which may occur when a child exits by itself
while being shut down by the supervisor.

@HansN
Copy link
Contributor

HansN commented Sep 28, 2021

I checked the results of the testing, and there are no problems with the new test cases, neither in maint, master or maint-24 (the coming patch).

@HansN
Copy link
Contributor

HansN commented Sep 28, 2021

One thing left to do is to write a release note, so if you have a suggestion for that it would be nice :-)

Ummm... not sure sweat_smile FWIW, this is what I put as commit message, maybe you can distill something from that? I can't think of anything better that describes both the problem and the solution...

What about something like:

Fixed a bug that could cause a race: if the supervisor died between that
it unlinked and that it sent the exit signal, the child could become an orphan.
There was also a risk for spurious SUPERVISOR REPORTS.

@Maria-12648430
Copy link
Contributor Author

@HansN hm, I don't think that explains it very well... IMO it's misleading even.

Fixed a bug that could cause a race: if the supervisor died between that
it unlinked and that it sent the exit signal, the child could become an orphan.

There wasn't a race here, in the sense that I would use the word. What could happen was that the supervisor unlinked the child and then died before sending the shutdown signal, which in turn would result in an orphaned child. But if anything, the supervisor was only racing it's own death there, and it wasn't causing that race.

There was also a risk for spurious SUPERVISOR REPORTS.

Now those were caused by a race between a supervisor shutting down a child and that child exiting by itself at the same time. I wouldn't call it a risk though. I mean, it wasn't anything dangerous 😉 Just puzzling and needlessly worrying maybe.

@Maria-12648430
Copy link
Contributor Author

... but I really have no idea what a good synonym for "bad side-effect of sudden death at a bad time" is 😬

@Maria-12648430
Copy link
Contributor Author

"leaking children"? 😅😅😅

@juhlig
Copy link
Contributor

juhlig commented Sep 28, 2021

"leaking children"? 😅😅😅

Yeah, children do that sometimes ^^;;; Fix: Diapers

@Maria-12648430
Copy link
Contributor Author

You're not exactly helpful 😝

@juhlig
Copy link
Contributor

juhlig commented Sep 28, 2021

You're not exactly helpful 😝

I wasn't trying to be 😛

What about this?

Fixed a bug that could cause a child to become orphaned
when a supervisor died between unlinking and sending the
shutdown signal to this child.

And the other, how does this sound?

There was also a possibility for erratic SUPERVISOR REPORTs
caused by a race between a supervisor shutting down a
child and that child exiting by itself at the same time.

(@HansN @rickard-green)

@Maria-12648430
Copy link
Contributor Author

Sounds good to me, what do the others think?

@rickard-green
Copy link
Contributor

Sounds good! I guess that the part about the erratic supervisor reports cover the loss of the real exit reason resulting in a noproc exit reason. Do you agree?

@Maria-12648430
Copy link
Contributor Author

Sounds good! I guess that the part about the erratic supervisor reports cover the loss of the real exit reason resulting in a noproc exit reason. Do you agree?

Yes 😄

@rickard-green
Copy link
Contributor

@Maria-12648430 & @juhlig Nice work on this PR, thanks! Everything is now prepared for patch of this branch, including forward merge to maint and master. If nothing unexpected should happen the patch will be released tomorrow. This PR should be automatically closed and marked as merged when the patch is pushed to github.

@rickard-green rickard-green added this to the OTP-24.1.1 milestone Sep 29, 2021
@Maria-12648430
Copy link
Contributor Author

Great 🤩 Always nice to work with you all 😃

@rickard-green rickard-green merged commit bcda2c6 into erlang:maint-24 Sep 30, 2021
@garazdawi
Copy link
Contributor

I stumbled over a bug report from 2013 that is very similar to this, but not exactly. The bug report said that the exit reason of a process may be lost during a shutdown race if:

  1. child dies
  2. monitor(Child)
  3. unlink(Child)
  4. receive after 0 end.
  5. 'EXIT' message arrives with real reason.

From what I can tell this PR fixes that problem as well. Possibly this race also got a lot less likely when we redid how process interactions work in erts to use signals instead of taking locks of the target process.

Just thought I'd add this comment here so that anyone who goes looking for a fix to that issue will know where it was fixed.

@Maria-12648430
Copy link
Contributor Author

@garazdawi the unlink is there as a defense against late EXIT messages. Like @rickard-green, I'm not sure that a stray EXIT would not mess something up. I think it won't, but the supervisor code is a bit haywiry and I'm unwilling to take any unnecessary chances 😅

That said, a peculiarity of unlink is that the related EXIT message, when arriving after the call, are dropped. So, with a receive after 0 following the unlink, we either do flush out an EXIT message that arrived before the unlink call, or there won't be any arriving later. In either case, no stray EXITs 😉

@lhoguin
Copy link
Contributor

lhoguin commented Oct 25, 2021

Any reason why you didn't include shutdown here? https://github.com/erlang/otp/blob/master/lib/stdlib/src/supervisor.erl#L921-L936 And here? https://github.com/erlang/otp/blob/master/lib/stdlib/src/supervisor.erl#L1032-L1054

We are still seeing the shutdown_error message with reason shutdown and I think it can only come from either of those two places.

@Maria-12648430
Copy link
Contributor Author

TBH, I don't remember 🤷 But I guess it was just an oversight, at least I don't see a reason right now.

@juhlig
Copy link
Contributor

juhlig commented Jul 7, 2022

@juhlig can we have a short chat about changing _Mon to Mon please? It brakes a feature we use in production. Thanks in advance.

Hm, it is Mon right now, so do you mean changing Mon to _Mon?

I'm pretty curious what feature you can (un-)break by (re-)naming a variable =^^= If you want to tell me about it, just PM me on Erlang Forums.

But however that may be, I don't carry any special weight with OTP whatsoever, I was just co-author to this PR, nothing more. So I'd have to make another PR and explain the reasons, just like everyone else, ie like yourself 😉

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
team:VM Assigned to OTP team VM testing currently being tested, tag is used by OTP internal CI
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Race during the process self-termination and terminate via supervisor
8 participants