Compare commits
3 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 897233c75f | |||
| 3e928bb2f6 | |||
| 04491e70af |
@@ -65,6 +65,15 @@ namespace Oxide.Plugins
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
private const int MaxBackoffMs = 5000;
|
private const int MaxBackoffMs = 5000;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// How long a link must stay up before its drop counts as an outage rather than a
|
||||||
|
/// refusal. The backoff resets only past it: a sidecar that closes every connection at
|
||||||
|
/// once — one refusing a plugin that names another server (D155), or one crash-looping —
|
||||||
|
/// would otherwise be redialled twice a second for ever, rebuilding the boards on the
|
||||||
|
/// main thread and printing two console lines each time.
|
||||||
|
/// </summary>
|
||||||
|
private const int StableLinkMs = 10000;
|
||||||
|
|
||||||
/// <summary>The longest line accepted from the sidecar. Over-long lines are discarded.</summary>
|
/// <summary>The longest line accepted from the sidecar. Over-long lines are discarded.</summary>
|
||||||
private const int MaxInboundLineBytes = 1024 * 1024;
|
private const int MaxInboundLineBytes = 1024 * 1024;
|
||||||
|
|
||||||
@@ -244,6 +253,13 @@ namespace Oxide.Plugins
|
|||||||
|
|
||||||
_bootId = ResolveBootId();
|
_bootId = ResolveBootId();
|
||||||
_wipeId = ResolveWipeId();
|
_wipeId = ResolveWipeId();
|
||||||
|
|
||||||
|
// Before the link thread, not in `Loaded`: both frameworks call `Init` first, and a
|
||||||
|
// thread started here with `_config` still null dials the 7799 fallback. With one
|
||||||
|
// server per host that is its own sidecar by coincidence; with two it is the OTHER
|
||||||
|
// server's, whose sidecar then files this server's history under that one's id
|
||||||
|
// (found by the phase 18 walk, D154).
|
||||||
|
LoadConfigValues();
|
||||||
_running = true;
|
_running = true;
|
||||||
|
|
||||||
// Expired link codes are dropped on a timer, not on lookup: an unconfirmed code is
|
// Expired link codes are dropped on a timer, not on lookup: an unconfirmed code is
|
||||||
@@ -496,7 +512,6 @@ namespace Oxide.Plugins
|
|||||||
|
|
||||||
private void Loaded()
|
private void Loaded()
|
||||||
{
|
{
|
||||||
LoadConfigValues();
|
|
||||||
Puts($"protocol {ProtocolVersion}, serverId '{_config.ServerId}', sidecar {_config.Host}:{_config.Port}");
|
Puts($"protocol {ProtocolVersion}, serverId '{_config.ServerId}', sidecar {_config.Host}:{_config.Port}");
|
||||||
|
|
||||||
// Here rather than at `OnServerInitialized`: the link thread starts in `Init`, so a
|
// Here rather than at `OnServerInitialized`: the link thread starts in `Init`, so a
|
||||||
@@ -564,6 +579,7 @@ namespace Oxide.Plugins
|
|||||||
{
|
{
|
||||||
TcpClient client = null;
|
TcpClient client = null;
|
||||||
Thread reader = null;
|
Thread reader = null;
|
||||||
|
System.Diagnostics.Stopwatch upFor = null;
|
||||||
|
|
||||||
int epoch = Interlocked.Increment(ref _epoch);
|
int epoch = Interlocked.Increment(ref _epoch);
|
||||||
|
|
||||||
@@ -582,7 +598,7 @@ namespace Oxide.Plugins
|
|||||||
_dead = false;
|
_dead = false;
|
||||||
_connected = true;
|
_connected = true;
|
||||||
_loggedConnectFailure = false; // so a LATER outage is reported again
|
_loggedConnectFailure = false; // so a LATER outage is reported again
|
||||||
backoffMs = 500;
|
upFor = System.Diagnostics.Stopwatch.StartNew();
|
||||||
|
|
||||||
Interlocked.Increment(ref _connects);
|
Interlocked.Increment(ref _connects);
|
||||||
Puts($"connected to {host}:{port}");
|
Puts($"connected to {host}:{port}");
|
||||||
@@ -654,14 +670,25 @@ namespace Oxide.Plugins
|
|||||||
if (!_running)
|
if (!_running)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
// A link that held is an outage: start again from the shortest wait. One that was
|
||||||
|
// closed on arrival keeps doubling (see StableLinkMs).
|
||||||
|
if (upFor != null && upFor.ElapsedMilliseconds >= StableLinkMs)
|
||||||
|
backoffMs = 500;
|
||||||
|
|
||||||
// Nothing is listening yet, or the sidecar restarted. Both are normal.
|
// Nothing is listening yet, or the sidecar restarted. Both are normal.
|
||||||
//
|
//
|
||||||
// `Wake`, not `Thread.Sleep`: Unload runs on the MAIN thread and joins this one, so
|
// A handle, not `Thread.Sleep`: Unload runs on the MAIN thread and joins this one,
|
||||||
// an uninterruptible sleep here is a stall of up to MaxBackoffMs on every reload —
|
// so an uninterruptible sleep here is a stall of up to MaxBackoffMs on every reload
|
||||||
// Oxide reports it as `Calling 'Unload' took 1918ms`, and the server is frozen for
|
// — Oxide reports it as `Calling 'Unload' took 1918ms`, and the server is frozen for
|
||||||
// that whole time. Unload sets `_running` false and signals `Wake`, so waiting on
|
// that whole time. Unload sets `_stopping`, so waiting on it turns that stall into
|
||||||
// the handle turns that stall into an immediate return.
|
// an immediate return.
|
||||||
Wake.WaitOne(backoffMs);
|
//
|
||||||
|
// `_stopping`, not `Wake`, for the reason `_stopping` gives: `Emit` signals `Wake`
|
||||||
|
// on every frame, so a backoff waited on it lasted until the next hook fired. That
|
||||||
|
// was invisible while a failed connect was silent; against a sidecar that refuses
|
||||||
|
// (D155) the phase 18 walk measured some 250 redials a second, each printing two
|
||||||
|
// console lines and rebuilding the boards.
|
||||||
|
_stopping.WaitOne(backoffMs);
|
||||||
backoffMs = Math.Min(backoffMs * 2, MaxBackoffMs);
|
backoffMs = Math.Min(backoffMs * 2, MaxBackoffMs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user