internal void Exit(ref bool lockTaken)
 {
     try {
         MonitorUtils.Exit(this, ref lockTaken);
     } finally {
         if (!lockTaken)
         {
             _locked--;
         }
     }
 }
 internal void Enter(ref bool lockTaken)
 {
     try {
         MonitorUtils.Enter(this, ref lockTaken);
     } finally {
         if (lockTaken)
         {
             _locked++;
         }
     }
 }
Esempio n. 3
0
        public static RubyMutex /*!*/ Unlock(RubyMutex /*!*/ self)
        {
            bool lockTaken = true;

            try {
                MonitorUtils.Exit(self._mutex, ref lockTaken);
            } finally {
                if (!lockTaken)
                {
                    self._isLocked = false;
                }
            }
            return(self);
        }
Esempio n. 4
0
        public static bool TryLock(RubyMutex /*!*/ self)
        {
            bool lockTaken = false;

            try {
                MonitorUtils.TryEnter(self._mutex, ref lockTaken);
            } finally {
                if (lockTaken)
                {
                    self._isLocked = true;
                }
            }
            return(lockTaken);
        }
Esempio n. 5
0
        public static object Synchronize(BlockParam criticalSection, RubyMutex /*!*/ self)
        {
            bool lockTaken = false;

            try {
                MonitorUtils.Enter(self._mutex, ref lockTaken);
                self._isLocked = lockTaken;
                object result;
                criticalSection.Yield(out result);
                return(result);
            } finally {
                if (lockTaken)
                {
                    MonitorUtils.Exit(self._mutex, ref lockTaken);
                    self._isLocked = lockTaken;
                }
            }
        }
Esempio n. 6
0
 private static void SetCritical(RubyContext /*!*/ context, bool value)
 {
     Debug.Assert(context.RubyOptions.Compatibility < RubyCompatibility.Ruby19);
     if (value)
     {
         bool lockTaken = false;
         try {
             MonitorUtils.Enter(context.CriticalMonitor, ref lockTaken);
         } finally {
             // thread could have been aborted just before/after Monitor.Enter acquired the lock:
             if (lockTaken)
             {
                 context.CriticalThread = Thread.CurrentThread;
             }
         }
     }
     else
     {
         Monitor.Exit(context.CriticalMonitor);
         context.CriticalThread = null;
     }
 }
        public async Task <bool> UpdateServer(Server server)
        {
            var serverPath = new DirectoryInfo(server.Path);

            if (!serverPath.Exists)
            {
                serverPath.Create();
            }

            using (var scope = _serviceScopeFactory.CreateScope())
                using (var db = scope.ServiceProvider.GetRequiredService <MonitorDBContext>())
                {
                    var scopedServices = scope.ServiceProvider;

                    StringBuilder outputStringBuilder = new StringBuilder();

                    // Params stuff
                    List <string[]> parameterBuilder = new List <string[]>
                    {
                        new string[] { "+login", "anonymous" },                 // TODO: Allow user logins
                        new string[] { "+force_install_dir", $"\"{serverPath.FullName}\"" }
                    };

                    // F*****g dynamic shit param builder what the f**k
                    List <string> updateText = new List <string>
                    {
                        server.Game.SteamID?.ToString(CultureInfo.InvariantCulture)
                    };
                    if (!String.IsNullOrEmpty(server.Branch) && server.Branch != "public")
                    {
                        updateText.Add("-beta");
                        updateText.Add(server.Branch);
                        if (!String.IsNullOrEmpty(server.BranchPassword))
                        {
                            updateText.Add("-betapassword");
                            updateText.Add(server.BranchPassword);
                        }

                        // TODO: Should add 'validate' param?
                    }

                    // app_update param builder
                    StringBuilder updateParams = new StringBuilder();
                    if (updateText.Count > 1)
                    {
                        updateParams.Append("\"");
                    }
                    updateParams.Append(String.Join(" ", updateText));
                    if (updateText.Count > 1)
                    {
                        updateParams.Append("\"");
                    }

                    parameterBuilder.Add(new string[] { "+app_update", updateParams.ToString() });

                    parameterBuilder.Add(new string[] { "+quit" });

                    string steamCMDArguments = String.Join(" ", parameterBuilder.Select(param => String.Join(" ", param)).ToArray());


                    _logger.LogInformation("Starting SteamCMD with arguments: {0}", steamCMDArguments);


                    // Init proccess listeners

                    IPtyConnection steamCMDProc = null;

                    var         downloadProgressRegex = @"Update state \((.+?)\) downloading, progress: ([\d.]+) \((\d*) \/ (\d*)\)";
                    CultureInfo ci = (CultureInfo)CultureInfo.CurrentCulture.Clone();
                    ci.NumberFormat.CurrencyDecimalSeparator = ".";

                    //DataReceivedEventHandler outputEventHandler = (sender, e) =>
                    EventHandler outputEventHandler = (sender, e2) =>
                    {
                        var e = (CustomDataReceivedEventArgs)e2;
                        _logger.LogDebug("SteamCMD Log {0} - {1}: {2}", server.Id, steamCMDProc.Pid, e.Data);

                        UpdateMessage?.Invoke(server, new ConsoleEventArgs()
                        {
                            NewLine = e.Data
                        });

                        if (!string.IsNullOrEmpty(e.Data))
                        {
                            Match match = Regex.Match(e.Data, downloadProgressRegex, RegexOptions.IgnoreCase);
                            if (match.Success)
                            {
                                UpdateProgress?.Invoke(server, new ServerUpdateProgressEventArgs()
                                {
                                    Progress = float.Parse(match.Groups[2].Value, NumberStyles.Any, ci)
                                });
                            }
                        }
                    };

                    //DataReceivedEventHandler errorEventHandler = (sender, e) =>
                    EventHandler errorEventHandler = (sender, e2) =>
                    {
                        var e = (CustomDataReceivedEventArgs)e2;
                        _logger.LogWarning("SteamCMD emitted {0} - {1}: {2}", server.Id, steamCMDProc.Pid, e.Data);

                        UpdateMessage?.Invoke(server, new ConsoleEventArgs()
                        {
                            NewLine = e.Data,
                            IsError = true
                        });
                    };

                    // Start process
                    var hasErrored          = false;
                    var processExitedCTS    = new CancellationTokenSource();
                    var processExitedCToken = processExitedCTS.Token;
                    try
                    {
                        steamCMDProc = await _steamCMDService.CreateSteamCMD(steamCMDArguments);

                        //steamCMDProc.OutputDataReceived += outputEventHandler;
                        //steamCMDProc.ErrorDataReceived += errorEventHandler;

                        //steamCMDProc.Start();
                        //steamCMDProc.BeginOutputReadLine();
                        //steamCMDProc.BeginErrorReadLine();

                        // Exit event
                        var processExitedTcs = new TaskCompletionSource <uint>();
                        steamCMDProc.ProcessExited += (sender, e) =>
                        {
                            processExitedTcs.TrySetResult((uint)steamCMDProc.ExitCode);
                            processExitedCTS.Cancel();
                            //steamCMDProc.ReaderStream.Close();
                            //steamCMDProc.ReaderStream.Dispose();
                        };

                        server.UpdatePID = steamCMDProc.Pid;

                        db.Update(server);
                        await db.SaveChangesAsync();

                        ServerUpdateStart?.Invoke(server, new EventArgs());                 // Event


                        // Reading console
                        var encoding = new UTF8Encoding(encoderShouldEmitUTF8Identifier: false);
                        var decoder  = encoding.GetDecoder();
                        var sb       = new StringBuilder();

                        var byteBuffer        = new byte[1024];
                        var maxCharsPerBuffer = encoding.GetMaxCharCount(1024);
                        var charBuffer        = new char[maxCharsPerBuffer];

                        int  currentLinePos      = 0;
                        bool bLastCarriageReturn = false;
                        while (!processExitedTcs.Task.IsCompleted)
                        {
                            try
                            {
                                var bytesRead = await steamCMDProc.ReaderStream.ReadAsync(byteBuffer, 0, byteBuffer.Length).WithCancellation(processExitedCToken);

                                if (bytesRead == 0)
                                {
                                    break;
                                }

                                int charLen = decoder.GetChars(byteBuffer, 0, bytesRead, charBuffer, 0);
                                sb !.Append(charBuffer, 0, charLen);

                                MonitorUtils.MoveLinesFromStringBuilderToMessageQueue(ref currentLinePos, ref bLastCarriageReturn, sb,
                                                                                      (line) => outputEventHandler?.Invoke(steamCMDProc, new CustomDataReceivedEventArgs(line)));
                            }
                            catch (OperationCanceledException)
                            {
                                break;
                            }
                        }

                        if (!processExitedTcs.Task.IsCompleted)
                        {
                            await processExitedTcs.Task;
                        }


                        /*
                         * var readStdOut = Task.Run(async delegate
                         * {
                         *      string? line = null;
                         *      //while ((line = await steamCMDProc.StandardOutput.ReadLineAsync()) != null)
                         *      while (steamCMDProc.StandardOutput.Peek() > -1)
                         *      {
                         *              line = steamCMDProc.StandardOutput.ReadLine();
                         *              _logger.LogWarning("Read line! {0}", line);
                         *              outputEventHandler.Invoke(steamCMDProc, new CustomDataReceivedEventArgs(line));
                         *      }
                         * });
                         * var readErrOut = Task.Run(async delegate
                         * {
                         *      string? line = null;
                         *      //while ((line = await steamCMDProc.StandardError.ReadLineAsync()) != null)
                         *      while (steamCMDProc.StandardError.Peek() > -1)
                         *      {
                         *              line = steamCMDProc.StandardError.ReadLine();
                         *              errorEventHandler.Invoke(steamCMDProc, new CustomDataReceivedEventArgs(line));
                         *      }
                         * });
                         *
                         * await Task.WhenAll(readStdOut, readErrOut);
                         */

                        //await steamCMDProc.WaitForExitAsync();
                        //steamCMDProc.WaitForExit();

                        //steamCMDProc.CancelOutputRead();
                        //steamCMDProc.CancelErrorRead();

                        try
                        {
                            if (steamCMDProc.ExitCode != 0)
                            {
                                hasErrored = true;
                                throw new Exception();
                            }
                        }
                        catch (InvalidOperationException err)
                        {
                            // Do nothing, for some f*****g reason it seems it can't get the exit code
                        }
                    }
                    catch (Exception err)
                    {
                        _logger.LogError(err, "There has been an error while updating the server via SteamCMD");
                        return(false);
                    }
                    finally
                    {
                        _logger.LogInformation("Update finished for server {0}!", server.Id);

                        server.UpdatePID = null;
                        db.Update(server);

                        await db.SaveChangesAsync();


                        ServerUpdated?.Invoke(server, new ServerUpdateEventArgs()
                        {
                            Error = hasErrored
                        });

                        if (steamCMDProc != null)
                        {
                            //steamCMDProc.OutputDataReceived -= outputEventHandler;
                            //steamCMDProc.ErrorDataReceived -= errorEventHandler;
                            steamCMDProc.Dispose();
                        }
                        processExitedCTS.Dispose();
                    }
                }

            return(true);
        }