Add exception tolerance to SharedDoAfterSystem. (#43088)
This commit is contained in:
parent
79590e2a69
commit
35177173e2
|
|
@ -2,14 +2,16 @@ using Content.Shared.Gravity;
|
|||
using Content.Shared.Hands.Components;
|
||||
using Content.Shared.Hands.EntitySystems;
|
||||
using Content.Shared.Interaction;
|
||||
using Content.Shared.Physics;
|
||||
using Robust.Shared.Utility;
|
||||
using Robust.Shared.Exceptions;
|
||||
using Robust.Shared.Network;
|
||||
|
||||
namespace Content.Shared.DoAfter;
|
||||
|
||||
public abstract partial class SharedDoAfterSystem : EntitySystem
|
||||
{
|
||||
[Dependency] private readonly IDynamicTypeFactory _factory = default!;
|
||||
[Dependency] private readonly INetManager _netManager = default!;
|
||||
[Dependency] private readonly IRuntimeLog _runtimeLog = default!;
|
||||
[Dependency] private readonly SharedGravitySystem _gravity = default!;
|
||||
[Dependency] private readonly SharedInteractionSystem _interaction = default!;
|
||||
[Dependency] private readonly SharedHandsSystem _hands = default!;
|
||||
|
|
@ -27,7 +29,51 @@ public abstract partial class SharedDoAfterSystem : EntitySystem
|
|||
var enumerator = EntityQueryEnumerator<ActiveDoAfterComponent, DoAfterComponent>();
|
||||
while (enumerator.MoveNext(out var uid, out var active, out var comp))
|
||||
{
|
||||
Update(uid, active, comp, time, xformQuery, handsQuery);
|
||||
|
||||
try
|
||||
{
|
||||
Update(uid, active, comp, time, xformQuery, handsQuery);
|
||||
}
|
||||
// ReSharper disable once RedundantCatchClause
|
||||
catch (Exception e)
|
||||
{
|
||||
#if EXCEPTION_TOLERANCE
|
||||
// Doafter in question failed to complete..
|
||||
// Doafters are kind of a critical game mechanic, so we specially handle failure.
|
||||
_runtimeLog.LogException(e, $"{nameof(SharedDoAfterSystem)} on {ToPrettyString(uid)}");
|
||||
|
||||
if (_netManager.IsClient)
|
||||
continue; // Move along, we can't cancel these ourselves and just need to not completely die.
|
||||
|
||||
// Cancel all the doafters for this entity to avoid repeats.
|
||||
// We don't try to remove them ourselves to keep the logic reasonable.
|
||||
foreach (var (key, doAfter) in comp.DoAfters)
|
||||
{
|
||||
try
|
||||
{
|
||||
InternalCancel(doAfter, comp);
|
||||
}
|
||||
catch (Exception e2)
|
||||
{
|
||||
_runtimeLog.LogException(e2, $"{nameof(SharedDoAfterSystem)} failed to cleanup {doAfter} @ {key} while handling a failure.");
|
||||
// REMARK: As written, InternalCancel will always do the necessary side effect of
|
||||
// configuring the cancellation time. We need this side effect, so dear reader
|
||||
// if you ever make it so InternalCancel can throw an exception before that
|
||||
// happens, update this to set cancel time itself in a finally block.
|
||||
//
|
||||
// If the doafter is one using async, this CAN result in that task leaking forever.
|
||||
// So we check that here, too.
|
||||
if (comp.AwaitedDoAfters.Remove(doAfter.Index, out var tcs))
|
||||
{
|
||||
tcs.TrySetCanceled();
|
||||
}
|
||||
}
|
||||
}
|
||||
#else
|
||||
throw; // No tolerance, just rethrow.
|
||||
#endif
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue