Skip to content

Commit 8d70cce

Browse files
authored
Propagate CoordinatedShutdown reason to application exit code (#7684)
1 parent d87acf5 commit 8d70cce

File tree

4 files changed

+51
-6
lines changed

4 files changed

+51
-6
lines changed

src/core/Akka.API.Tests/verify/CoreAPISpec.ApproveCore.DotNet.verified.txt

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -579,30 +579,37 @@ namespace Akka.Actor
579579
public class ActorSystemTerminateReason : Akka.Actor.CoordinatedShutdown.Reason
580580
{
581581
public static readonly Akka.Actor.CoordinatedShutdown.Reason Instance;
582+
public override int ExitCode { get; }
582583
}
583584
public class ClrExitReason : Akka.Actor.CoordinatedShutdown.Reason
584585
{
585586
public static readonly Akka.Actor.CoordinatedShutdown.Reason Instance;
587+
public override int ExitCode { get; }
586588
}
587589
public class ClusterDowningReason : Akka.Actor.CoordinatedShutdown.Reason
588590
{
589591
public static readonly Akka.Actor.CoordinatedShutdown.Reason Instance;
592+
public override int ExitCode { get; }
590593
}
591594
public class ClusterJoinUnsuccessfulReason : Akka.Actor.CoordinatedShutdown.Reason
592595
{
593596
public static readonly Akka.Actor.CoordinatedShutdown.Reason Instance;
597+
public override int ExitCode { get; }
594598
}
595599
public class ClusterLeavingReason : Akka.Actor.CoordinatedShutdown.Reason
596600
{
597601
public static readonly Akka.Actor.CoordinatedShutdown.Reason Instance;
602+
public override int ExitCode { get; }
598603
}
599-
public class Reason
604+
public abstract class Reason
600605
{
601606
protected Reason() { }
607+
public abstract int ExitCode { get; }
602608
}
603609
public class UnknownReason : Akka.Actor.CoordinatedShutdown.Reason
604610
{
605611
public static readonly Akka.Actor.CoordinatedShutdown.Reason Instance;
612+
public override int ExitCode { get; }
606613
}
607614
}
608615
public sealed class CoordinatedShutdownExtension : Akka.Actor.ExtensionIdProvider<Akka.Actor.CoordinatedShutdown>

src/core/Akka.API.Tests/verify/CoreAPISpec.ApproveCore.Net.verified.txt

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -579,30 +579,37 @@ namespace Akka.Actor
579579
public class ActorSystemTerminateReason : Akka.Actor.CoordinatedShutdown.Reason
580580
{
581581
public static readonly Akka.Actor.CoordinatedShutdown.Reason Instance;
582+
public override int ExitCode { get; }
582583
}
583584
public class ClrExitReason : Akka.Actor.CoordinatedShutdown.Reason
584585
{
585586
public static readonly Akka.Actor.CoordinatedShutdown.Reason Instance;
587+
public override int ExitCode { get; }
586588
}
587589
public class ClusterDowningReason : Akka.Actor.CoordinatedShutdown.Reason
588590
{
589591
public static readonly Akka.Actor.CoordinatedShutdown.Reason Instance;
592+
public override int ExitCode { get; }
590593
}
591594
public class ClusterJoinUnsuccessfulReason : Akka.Actor.CoordinatedShutdown.Reason
592595
{
593596
public static readonly Akka.Actor.CoordinatedShutdown.Reason Instance;
597+
public override int ExitCode { get; }
594598
}
595599
public class ClusterLeavingReason : Akka.Actor.CoordinatedShutdown.Reason
596600
{
597601
public static readonly Akka.Actor.CoordinatedShutdown.Reason Instance;
602+
public override int ExitCode { get; }
598603
}
599-
public class Reason
604+
public abstract class Reason
600605
{
601606
protected Reason() { }
607+
public abstract int ExitCode { get; }
602608
}
603609
public class UnknownReason : Akka.Actor.CoordinatedShutdown.Reason
604610
{
605611
public static readonly Akka.Actor.CoordinatedShutdown.Reason Instance;
612+
public override int ExitCode { get; }
606613
}
607614
}
608615
public sealed class CoordinatedShutdownExtension : Akka.Actor.ExtensionIdProvider<Akka.Actor.CoordinatedShutdown>

src/core/Akka.Tests/Actor/CoordinatedShutdownSpec.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ private List<string> CheckTopologicalSort(Dictionary<string, Phase> phases)
5353

5454
private class CustomReason : CoordinatedShutdown.Reason
5555
{
56+
public override int ExitCode => 999;
5657
}
5758

5859
private static CoordinatedShutdown.Reason customReason = new CustomReason();

src/core/Akka/Actor/CoordinatedShutdown.cs

Lines changed: 34 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -156,16 +156,33 @@ public static CoordinatedShutdown Get(ActorSystem sys)
156156
public const string PhaseBeforeActorSystemTerminate = "before-actor-system-terminate";
157157
public const string PhaseActorSystemTerminate = "actor-system-terminate";
158158

159-
159+
/// <summary>
160+
/// Common exit codes supported out of the box.
161+
/// Note: When adding new exit codes, make sure that the exit code adheres
162+
/// to the Linux standard.
163+
/// See: https://manpages.ubuntu.com/manpages/lunar/man3/sysexits.h.3head.html
164+
/// See: https://manpages.ubuntu.com/manpages/noble/man3/EXIT_SUCCESS.3const.html
165+
/// </summary>
166+
internal enum CommonExitCodes
167+
{
168+
Ok = 0,
169+
UnknownReason = 1,
170+
// Exit code 2 is reserved for Linux Bash for "Incorrect Usage"
171+
ClusterDowned = 3,
172+
ClusterJoinFailed = 4,
173+
// Exit codes 64-78 is reserved by Linux sysexits.h
174+
// Exit codes 126 and above is reserved by Linux shell
175+
}
160176

161177
/// <summary>
162178
/// Reason for the shutdown, which can be used by tasks in case they need to do
163179
/// different things depending on what caused the shutdown. There are some
164180
/// predefined reasons, but external libraries applications may also define
165181
/// other reasons.
166182
/// </summary>
167-
public class Reason
183+
public abstract class Reason
168184
{
185+
public abstract int ExitCode { get; }
169186
protected Reason()
170187
{
171188

@@ -179,6 +196,8 @@ public class UnknownReason : Reason
179196
{
180197
public static readonly Reason Instance = new UnknownReason();
181198

199+
public override int ExitCode => (int)CommonExitCodes.UnknownReason;
200+
182201
private UnknownReason()
183202
{
184203

@@ -192,6 +211,8 @@ public class ActorSystemTerminateReason : Reason
192211
{
193212
public static readonly Reason Instance = new ActorSystemTerminateReason();
194213

214+
public override int ExitCode => (int)CommonExitCodes.Ok;
215+
195216
private ActorSystemTerminateReason()
196217
{
197218

@@ -205,6 +226,8 @@ public class ClrExitReason : Reason
205226
{
206227
public static readonly Reason Instance = new ClrExitReason();
207228

229+
public override int ExitCode => (int)CommonExitCodes.Ok;
230+
208231
private ClrExitReason()
209232
{
210233

@@ -219,6 +242,8 @@ public class ClusterDowningReason : Reason
219242
{
220243
public static readonly Reason Instance = new ClusterDowningReason();
221244

245+
public override int ExitCode => (int)CommonExitCodes.ClusterDowned;
246+
222247
private ClusterDowningReason()
223248
{
224249

@@ -233,6 +258,8 @@ public class ClusterLeavingReason : Reason
233258
{
234259
public static readonly Reason Instance = new ClusterLeavingReason();
235260

261+
public override int ExitCode => (int)CommonExitCodes.Ok;
262+
236263
private ClusterLeavingReason()
237264
{
238265

@@ -245,6 +272,9 @@ private ClusterLeavingReason()
245272
public class ClusterJoinUnsuccessfulReason : Reason
246273
{
247274
public static readonly Reason Instance = new ClusterJoinUnsuccessfulReason();
275+
276+
public override int ExitCode => (int)CommonExitCodes.ClusterJoinFailed;
277+
248278
private ClusterJoinUnsuccessfulReason() { }
249279
}
250280

@@ -646,7 +676,7 @@ internal static void InitPhaseActorSystemTerminate(ActorSystem system, Config co
646676
{
647677
if (!system.WhenTerminated.Wait(timeout) && !coord._runningClrHook)
648678
{
649-
Environment.Exit(0);
679+
Environment.Exit(coord.ShutdownReason?.ExitCode ?? 0);
650680
}
651681
});
652682
}
@@ -665,7 +695,7 @@ internal static void InitPhaseActorSystemTerminate(ActorSystem system, Config co
665695
}
666696
else if (exitClr)
667697
{
668-
Environment.Exit(0);
698+
Environment.Exit(coord.ShutdownReason?.ExitCode ?? 0);
669699
return TaskEx.Completed;
670700
}
671701
else

0 commit comments

Comments
 (0)