diff --git a/Application/IW4MServer.cs b/Application/IW4MServer.cs index 48d4c9695..bc4347bb8 100644 --- a/Application/IW4MServer.cs +++ b/Application/IW4MServer.cs @@ -236,7 +236,7 @@ namespace IW4MAdmin private async Task CreatePluginTask(IPlugin plugin, GameEvent gameEvent) { // we don't want to run the events on parser plugins - if (plugin is ScriptPlugin scriptPlugin && scriptPlugin.IsParser) + if (plugin is ScriptPlugin { IsParser: true }) { return; } @@ -248,6 +248,11 @@ namespace IW4MAdmin { await plugin.OnEventAsync(gameEvent, this).WithWaitCancellation(tokenSource.Token); } + catch (OperationCanceledException) + { + ServerLogger.LogWarning("Timed out executing event {EventType} for {Plugin}", gameEvent.Type, + plugin.Name); + } catch (Exception ex) { Console.WriteLine(loc["SERVER_PLUGIN_ERROR"].FormatExt(plugin.Name, ex.GetType().Name)); diff --git a/Application/Misc/ScriptPlugin.cs b/Application/Misc/ScriptPlugin.cs index d188bd40d..b1fc209ca 100644 --- a/Application/Misc/ScriptPlugin.cs +++ b/Application/Misc/ScriptPlugin.cs @@ -223,47 +223,49 @@ namespace IW4MAdmin.Application.Misc public async Task OnEventAsync(GameEvent gameEvent, Server server) { - if (_successfullyLoaded) + if (!_successfullyLoaded) { - try - { - await _onProcessing.WaitAsync(); - _scriptEngine.SetValue("_gameEvent", gameEvent); - _scriptEngine.SetValue("_server", server); - _scriptEngine.SetValue("_IW4MAdminClient", Utilities.IW4MAdminClient(server)); - _scriptEngine.Evaluate("plugin.onEventAsync(_gameEvent, _server)"); - } - - catch (JavaScriptException ex) - { - using (LogContext.PushProperty("Server", server.ToString())) - { - _logger.LogError(ex, - "Encountered JavaScript runtime error while executing {MethodName} for script plugin {Plugin} with event type {EventType} {@LocationInfo}", - nameof(OnEventAsync), Path.GetFileName(_fileName), gameEvent.Type, ex.Location); - } + return; + } - throw new PluginException("An error occured while executing action for script plugin"); + try + { + await _onProcessing.WaitAsync(); + _scriptEngine.SetValue("_gameEvent", gameEvent); + _scriptEngine.SetValue("_server", server); + _scriptEngine.SetValue("_IW4MAdminClient", Utilities.IW4MAdminClient(server)); + _scriptEngine.Evaluate("plugin.onEventAsync(_gameEvent, _server)"); + } + + catch (JavaScriptException ex) + { + using (LogContext.PushProperty("Server", server.ToString())) + { + _logger.LogError(ex, + "Encountered JavaScript runtime error while executing {MethodName} for script plugin {Plugin} with event type {EventType} {@LocationInfo}", + nameof(OnEventAsync), Path.GetFileName(_fileName), gameEvent.Type, ex.Location); } - catch (Exception ex) - { - using (LogContext.PushProperty("Server", server.ToString())) - { - _logger.LogError(ex, - "Encountered error while running {MethodName} for script plugin {Plugin} with event type {EventType}", - nameof(OnEventAsync), _fileName, gameEvent.Type); - } + throw new PluginException("An error occured while executing action for script plugin"); + } - throw new PluginException("An error occured while executing action for script plugin"); + catch (Exception ex) + { + using (LogContext.PushProperty("Server", server.ToString())) + { + _logger.LogError(ex, + "Encountered error while running {MethodName} for script plugin {Plugin} with event type {EventType}", + nameof(OnEventAsync), _fileName, gameEvent.Type); } - finally + throw new PluginException("An error occured while executing action for script plugin"); + } + + finally + { + if (_onProcessing.CurrentCount == 0) { - if (_onProcessing.CurrentCount == 0) - { - _onProcessing.Release(1); - } + _onProcessing.Release(1); } } } diff --git a/Plugins/ScriptPlugins/GameInterface.js b/Plugins/ScriptPlugins/GameInterface.js index 86395c432..3ba646143 100644 --- a/Plugins/ScriptPlugins/GameInterface.js +++ b/Plugins/ScriptPlugins/GameInterface.js @@ -37,7 +37,7 @@ let plugin = { break; case 'preconnect': // when the plugin is reloaded after the servers are started - if (servers[server.EndPoint] == null) { + if (servers[server.EndPoint] === undefined || servers[server.EndPoint] == null) { const enabled = initialize(server); if (!enabled) { @@ -222,7 +222,7 @@ const sendEvent = (server, responseExpected, event, subtype, client, data) => { let pendingCheckCount = 0; const start = new Date(); - while (pendingOut && pendingCheckCount <= 30) { + while (pendingOut && pendingCheckCount <= 10) { try { const out = server.GetServerDvar(outDvar); pendingOut = !(out == null || out === '' || out === 'null'); diff --git a/SharedLibraryCore/Server.cs b/SharedLibraryCore/Server.cs index 36b2214da..4ca487296 100644 --- a/SharedLibraryCore/Server.cs +++ b/SharedLibraryCore/Server.cs @@ -390,17 +390,48 @@ namespace SharedLibraryCore public string[] ExecuteServerCommand(string command) { - return this.ExecuteCommandAsync(command).GetAwaiter().GetResult(); + var tokenSource = new CancellationTokenSource(); + tokenSource.CancelAfter(TimeSpan.FromMilliseconds(400)); + + try + { + return this.ExecuteCommandAsync(command).WithWaitCancellation(tokenSource.Token).GetAwaiter().GetResult(); + } + catch + { + return null; + } } public string GetServerDvar(string dvarName) { - return this.GetDvarAsync(dvarName).GetAwaiter().GetResult()?.Value; + var tokenSource = new CancellationTokenSource(); + tokenSource.CancelAfter(TimeSpan.FromSeconds(400)); + try + { + return this.GetDvarAsync(dvarName).WithWaitCancellation(tokenSource.Token).GetAwaiter() + .GetResult()?.Value; + } + catch + { + return null; + } } - public void SetServerDvar(string dvarName, string dvarValue) + public bool SetServerDvar(string dvarName, string dvarValue) { - this.SetDvarAsync(dvarName, dvarValue).GetAwaiter().GetResult(); + var tokenSource = new CancellationTokenSource(); + tokenSource.CancelAfter(TimeSpan.FromSeconds(400)); + try + { + this.SetDvarAsync(dvarName, dvarValue).WithWaitCancellation(tokenSource.Token).GetAwaiter().GetResult(); + return true; + + } + catch + { + return false; + } } public EFClient GetClientByNumber(int clientNumber) => diff --git a/SharedLibraryCore/Utilities.cs b/SharedLibraryCore/Utilities.cs index 51fdf6fe9..02d5e8a11 100644 --- a/SharedLibraryCore/Utilities.cs +++ b/SharedLibraryCore/Utilities.cs @@ -956,6 +956,19 @@ namespace SharedLibraryCore } } + public static async Task WithWaitCancellation(this Task task, + CancellationToken cancellationToken) + { + var completedTask = await Task.WhenAny(task, Task.Delay(Timeout.Infinite, cancellationToken)); + if (completedTask == task) + { + return await task; + } + + cancellationToken.ThrowIfCancellationRequested(); + throw new InvalidOperationException("Infinite delay task completed."); + } + public static async Task WithTimeout(this Task task, TimeSpan timeout) { await Task.WhenAny(task, Task.Delay(timeout));