Exemple #1
0
        private void DisposeCore()
        {
            if (!Disposed)
            {
                Disposed = true;

                if (!ResponseFinished)
                {
                    // If the response is not finished then cancel any pending actions:
                    // 1. Call HttpClient.SendAsync
                    // 2. Response Stream.ReadAsync
                    // 3. Client stream
                    //    - Getting the Stream from the Request.HttpContent
                    //    - Holding the Request.HttpContent.SerializeToStream open
                    //    - Writing to the client stream
                    CancelCall();
                }
                else
                {
                    _writeStreamTcs?.TrySetCanceled();
                    _completeTcs?.TrySetCanceled();
                }

                _ctsRegistration?.Dispose();
                _deadlineTimer?.Dispose();
                HttpResponse?.Dispose();
                ClientStreamReader?.Dispose();
                ClientStreamWriter?.Dispose();

                // To avoid racing with Dispose, skip disposing the call CTS
                // This avoid Dispose potentially calling cancel on a disposed CTS
                // The call CTS is not exposed externally and all dependent registrations
                // are cleaned up
            }
        }
Exemple #2
0
        /// <summary>
        /// Clean up can be called by:
        /// 1. The user. AsyncUnaryCall.Dispose et al will call this on Dispose
        /// 2. <see cref="ValidateHeaders"/> will call dispose if errors fail validation
        /// 3. <see cref="FinishResponseAndCleanUp"/> will call dispose
        /// </summary>
        private void Cleanup(Status status)
        {
            if (!ResponseFinished)
            {
                // If the response is not finished then cancel any pending actions:
                // 1. Call HttpClient.SendAsync
                // 2. Response Stream.ReadAsync
                // 3. Client stream
                //    - Getting the Stream from the Request.HttpContent
                //    - Holding the Request.HttpContent.SerializeToStream open
                //    - Writing to the client stream
                CancelCall(status);
            }
            else
            {
                _callTcs.TrySetResult(status);

                ClientStreamWriter?.WriteStreamTcs.TrySetCanceled();
                ClientStreamWriter?.CompleteTcs.TrySetCanceled();
                ClientStreamReader?.HttpResponseTcs.TrySetCanceled();
            }

            Channel.FinishActiveCall(this);

            _ctsRegistration?.Dispose();
            _deadlineTimer?.Dispose();
            HttpResponse?.Dispose();
            ClientStreamReader?.Dispose();
            ClientStreamWriter?.Dispose();

            // To avoid racing with Dispose, skip disposing the call CTS.
            // This avoid Dispose potentially calling cancel on a disposed CTS.
            // The call CTS is not exposed externally and all dependent registrations
            // are cleaned up.
        }
Exemple #3
0
        /// <summary>
        /// Clean up can be called by:
        /// 1. The user. AsyncUnaryCall.Dispose et al will call this on Dispose
        /// 2. <see cref="ValidateHeaders"/> will call dispose if errors fail validation
        /// 3. <see cref="FinishResponse"/> will call dispose
        /// </summary>
        private void Cleanup(Status status)
        {
            if (!ResponseFinished)
            {
                // If the response is not finished then cancel any pending actions:
                // 1. Call HttpClient.SendAsync
                // 2. Response Stream.ReadAsync
                // 3. Client stream
                //    - Getting the Stream from the Request.HttpContent
                //    - Holding the Request.HttpContent.SerializeToStream open
                //    - Writing to the client stream
                CancelCall(status);
            }
            else
            {
                _writeStreamTcs?.TrySetCanceled();
                _writeCompleteTcs?.TrySetCanceled();

                // If response has successfully finished then the status will come from the trailers
                // If it didn't finish then complete with a status
                _callTcs.TrySetResult(status);
            }

            _ctsRegistration?.Dispose();
            _deadlineTimer?.Dispose();
            HttpResponse?.Dispose();
            ClientStreamReader?.Dispose();
            ClientStreamWriter?.Dispose();

            // To avoid racing with Dispose, skip disposing the call CTS
            // This avoid Dispose potentially calling cancel on a disposed CTS
            // The call CTS is not exposed externally and all dependent registrations
            // are cleaned up
        }
Exemple #4
0
        public virtual async Task Run(string forwardingBatchId, Predicate <MessageContext> filter, CancellationToken cancellationToken, int?expectedMessageCount)
        {
            IReceivingRawEndpoint         processor    = null;
            CancellationTokenRegistration?registration = null;

            try
            {
                shouldProcess      = filter;
                targetMessageCount = expectedMessageCount;
                actualMessageCount = 0;

                if (Log.IsDebugEnabled)
                {
                    Log.DebugFormat("Starting receiver");
                }

                var config = createEndpointConfiguration();
                syncEvent            = new TaskCompletionSource <bool>();
                stopCompletionSource = new TaskCompletionSource <bool>();
                registration         = cancellationToken.Register(() => { Task.Run(() => syncEvent.TrySetResult(true), CancellationToken.None).Ignore(); });

                processor = await RawEndpoint.Start(config).ConfigureAwait(false);

                Log.Info($"Forwarder for batch {forwardingBatchId} started receiving messages from {processor.TransportAddress}.");

                if (!expectedMessageCount.HasValue)
                {
                    if (Log.IsDebugEnabled)
                    {
                        Log.Debug("Running in timeout mode. Starting timer.");
                    }

                    timer.Change(TimeSpan.FromSeconds(45), Timeout.InfiniteTimeSpan);
                }
            }
            finally
            {
                if (Log.IsDebugEnabled)
                {
                    Log.DebugFormat($"Waiting for forwarder for batch {forwardingBatchId} to finish.");
                }

                await syncEvent.Task.ConfigureAwait(false);

                registration?.Dispose();
                if (processor != null)
                {
                    await processor.Stop().ConfigureAwait(false);
                }

                Log.Info($"Forwarder for batch {forwardingBatchId} finished forwarding all messages.");

                await Task.Run(() => stopCompletionSource.TrySetResult(true), CancellationToken.None).ConfigureAwait(false);
            }

            if (endedPrematurely || cancellationToken.IsCancellationRequested)
            {
                throw new Exception("We are in the process of shutting down. Safe to ignore.");
            }
        }
Exemple #5
0
        public Task RunAsync(CancellationToken cancellationToken)
        {
            var tcs = new TaskCompletionSource <object>();
            CancellationTokenRegistration?cancelTokenReg = null;

            cancelTokenReg = cancellationToken.Register(async delegate
            {
                tcs.TrySetCanceled(cancellationToken);
                await AbortAsync();
                cancelTokenReg?.Dispose();
            });

            StartAsync().Then(delegate
            {
                this.ExecutingTask.Then(delegate
                {
                    switch (this.Status)
                    {
                    case ProcessStatus.Executed:
                        tcs.TrySetResult(null);
                        break;

                    case ProcessStatus.Compensated:
                        tcs.TrySetCanceled();
                        break;

                    case ProcessStatus.Aborted:
                        tcs.TrySetException(this.state.Exception);
                        break;
                    }
                });
            });

            return(tcs.Task);
        }
        public void Dispose()
        {
            var _this = Interlocked.Exchange(ref this._this, null);

            if (_this == null)
            {
                return;
            }

            Interlocked.Exchange(ref _isAvail, 0L);
            _d?.Dispose();
            _d = null;

            if (_this.kvs.TryGetValue(CK, out var lck))
            {
                if (lck.ID == this.ID)
                {
                    _this.kvs.TryRemove(CK, out _);
                    lck.Dispose();
                }
                else if (!lck.IsAvailable)
                {
                    lck.Dispose();
                }
            }
        }
        public static async Task <bool> WaitOneAsync(this WaitHandle handle, int millisecondsTimeout, CancellationToken?cancellationToken)
        {
            RegisteredWaitHandle?         registeredHandle  = null;
            CancellationTokenRegistration?tokenRegistration = null;

            try
            {
                var tcs = new TaskCompletionSource <bool>();
                registeredHandle = ThreadPool.RegisterWaitForSingleObject(
                    handle,
                    (state, timedOut) => ((TaskCompletionSource <bool>)state).TrySetResult(!timedOut),
                    tcs,
                    millisecondsTimeout,
                    true);
                if (cancellationToken.HasValue)
                {
                    tokenRegistration = cancellationToken.Value.Register(
                        state => ((TaskCompletionSource <bool>)state).TrySetCanceled(),
                        tcs);
                }
                return(await tcs.Task.ConfigureAwait(false));
            }
            finally
            {
                if (registeredHandle != null)
                {
                    registeredHandle.Unregister(null);
                }

                tokenRegistration?.Dispose();
            }
        }
        private async void GracefulTerminationRequested()
        {
            if (Interlocked.Exchange(ref _StopAlreadyRequested, 1) == 1)
            {
                return;
            }

            await Task.Yield();

            lock (_Lock)
            {
                _CancellationTokenRegistration?.Dispose();
                _CancellationTokenRegistration = null;
            }

            Stop();
        }
Exemple #9
0
 protected virtual void ProcessOnExited(object sender, EventArgs e) {
     if (!_exitedEventPublished) {
         // this boolean does not seem useful but i have seen weird behaviors where the
         // exited event is called twice when we WaitForExit(), better safe than sorry
         _exitedEventPublished = true;
         _cancelRegistration?.Dispose();
         OnProcessExit?.Invoke(sender, e);
     }
 }
Exemple #10
0
        /// <summary>
        /// TBD
        /// </summary>
        /// <typeparam name="T">TBD</typeparam>
        /// <param name="self">TBD</param>
        /// <param name="messageFactory">Factory method that creates a message that can encapsulate the 'Sender' IActorRef</param>
        /// <param name="timeout">TBD</param>
        /// <param name="cancellationToken">TBD</param>
        /// <exception cref="ArgumentException">
        /// This exception is thrown if the system can't resolve the target provider.
        /// </exception>
        /// <returns>TBD</returns>
        public static Task <T> Ask <T>(this ICanTell self, Func <IActorRef, object> messageFactory, TimeSpan?timeout, CancellationToken cancellationToken)
        {
            IActorRefProvider provider = ResolveProvider(self);

            if (provider == null)
            {
                throw new ArgumentException("Unable to resolve the target Provider", nameof(self));
            }

            var result = TaskEx.NonBlockingTaskCompletionSource <T>();

            CancellationTokenSource timeoutCancellation = null;

            timeout = timeout ?? provider.Settings.AskTimeout;

            CancellationTokenRegistration?ctr1 = null;
            CancellationTokenRegistration?ctr2 = null;

            if (timeout != Timeout.InfiniteTimeSpan && timeout.Value > default(TimeSpan))
            {
                timeoutCancellation = new CancellationTokenSource();

                ctr1 = timeoutCancellation.Token.Register(() =>
                {
                    result.TrySetException(new AskTimeoutException($"Timeout after {timeout} seconds"));
                });

                timeoutCancellation.CancelAfter(timeout.Value);
            }

            if (cancellationToken.CanBeCanceled)
            {
                ctr2 = cancellationToken.Register(() => result.TrySetCanceled());
            }

            var future = provider.CreateFutureRef(result);
            var path   = future.Path;

            //The future actor needs to be unregistered in the temp container
            _ = result.Task.ContinueWith(t =>
            {
                provider.UnregisterTempActor(path);

                ctr1?.Dispose();
                ctr2?.Dispose();
                timeoutCancellation?.Dispose();
            }, TaskContinuationOptions.ExecuteSynchronously);

            //The future actor needs to be registered in the temp container
            provider.RegisterTempActor(future, path);
            var message = messageFactory(future);

            self.Tell(message, future);

            return(result.Task);
        }
Exemple #11
0
        public virtual async Task Run(Predicate <MessageContext> filter, CancellationToken cancellationToken, int?expectedMessageCount = null)
        {
            IReceivingRawEndpoint         processor    = null;
            CancellationTokenRegistration?registration = null;

            try
            {
                Log.DebugFormat("Started. Expectected message count {0}", expectedMessageCount);

                if (expectedMessageCount.HasValue && expectedMessageCount.Value == 0)
                {
                    return;
                }

                shouldProcess      = filter;
                targetMessageCount = expectedMessageCount;
                actualMessageCount = 0;
                Log.DebugFormat("Starting receiver");

                var config = createEndpointConfiguration();
                syncEvent            = new TaskCompletionSource <bool>();
                stopCompletionSource = new TaskCompletionSource <bool>();
                registration         = cancellationToken.Register(() => { Task.Run(() => syncEvent.TrySetResult(true), CancellationToken.None).Ignore(); });

                processor = await RawEndpoint.Start(config).ConfigureAwait(false);

                if (!expectedMessageCount.HasValue)
                {
                    Log.Debug("Running in timeout mode. Starting timer");
                    timer.Change(TimeSpan.FromSeconds(45), Timeout.InfiniteTimeSpan);
                }

                Log.InfoFormat("{0} started", GetType().Name);
            }
            finally
            {
                Log.DebugFormat("Waiting for {0} finish", GetType().Name);
                await syncEvent.Task.ConfigureAwait(false);

                registration?.Dispose();
                if (processor != null)
                {
                    await processor.Stop().ConfigureAwait(false);
                }

                await Task.Run(() => stopCompletionSource.TrySetResult(true), CancellationToken.None).ConfigureAwait(false);

                Log.DebugFormat("{0} finished", GetType().Name);
            }

            if (endedPrematurelly || cancellationToken.IsCancellationRequested)
            {
                throw new Exception("We are in the process of shutting down. Safe to ignore.");
            }
        }
Exemple #12
0
    void HandleCancel()
    {
        if (repeatModeState != null)
        {
            repeatModeState      = null;
            engine.StateChanged -= WatchStateChangedForRepeat;
        }

        durationCancellationRegistration?.Dispose();
        durationCancellationTokenSource?.Dispose();

        engine.Cancel();
    }
Exemple #13
0
        void SetTaskResult(bool result)
        {
            if (tcs == null)
            {
                return;
            }

            ctr?.Dispose();
            ctr = null;
            var stored = tcs;

            tcs = null;
            stored.SetResult(result);
        }
Exemple #14
0
        private void DisposeCore()
        {
            if (!Disposed)
            {
                // Locking on the call because:
                // 1. Its not exposed publically
                // 2. Nothing else locks on call
                // 3. We want to avoid allocating a private lock object
                lock (this)
                {
                    if (!Disposed)
                    {
                        Disposed = true;

                        if (!ResponseFinished)
                        {
                            // If the response is not finished then cancel any pending actions:
                            // 1. Call HttpClient.SendAsync
                            // 2. Response Stream.ReadAsync
                            // 3. Client stream
                            //    - Getting the Stream from the Request.HttpContent
                            //    - Holding the Request.HttpContent.SerializeToStream open
                            //    - Writing to the client stream
                            CancelCall();
                        }
                        else
                        {
                            _writeStreamTcs?.TrySetCanceled();
                            _writeCompleteTcs?.TrySetCanceled();
                        }

                        // If response has successfully finished then the status will come from the trailers
                        // If it didn't finish then complete with a Cancelled status
                        _callTcs.TrySetResult(StatusCode.Cancelled);

                        _ctsRegistration?.Dispose();
                        _deadlineTimer?.Dispose();
                        HttpResponse?.Dispose();
                        ClientStreamReader?.Dispose();
                        ClientStreamWriter?.Dispose();

                        // To avoid racing with Dispose, skip disposing the call CTS
                        // This avoid Dispose potentially calling cancel on a disposed CTS
                        // The call CTS is not exposed externally and all dependent registrations
                        // are cleaned up
                    }
                }
            }
        }
Exemple #15
0
        /// <summary>
        /// Allows awaiting a <see cref="WaitHandle"/>
        /// </summary>
        /// <param name="handle">The handle to await</param>
        /// <param name="millisecondsTimeout">The timeout period to return false if timed out</param>
        /// <param name="cancellationToken">The cancellation token to use to throw a <see cref="TaskCanceledException"/> if this token gets canceled</param>
        /// <returns>Returns true if the handle is free, false if it is not</returns>
        /// <exception cref="TaskCanceledException">Throws if the cancellation token is canceled</exception>
        public static async Task <bool> WaitOneAsync(this WaitHandle handle, int millisecondsTimeout, CancellationToken?cancellationToken)
        {
            // Create a handle that awaiting the original wait handle
            RegisteredWaitHandle registeredWaitHandle = null;

            // Store the token
            CancellationTokenRegistration?tokenRegistration = null;

            try
            {
                // Create a task completion source to await
                var tcs = new TaskCompletionSource <bool>();

                // Use RegisterWaitForSingleObject so we get a callback
                // once the wait handle has finished, and set the tcs result in that callback
                registeredWaitHandle = ThreadPool.RegisterWaitForSingleObject(
                    // The handle to wait on
                    handle,
                    // When it is finished, set the tcs result
                    (state, timedOut) => ((TaskCompletionSource <bool>)state).TrySetResult(!timedOut),
                    // Pass the tcs as the state so we don't have a reference to the parent tcs (optimization)
                    tcs,
                    // Set timeout if passed in
                    millisecondsTimeout,
                    // Run once don't keep resetting timeout
                    true);

                // Register to run the action and set the tcs as canceled
                // if the cancellation token itself is canceled
                // which will throw a TaskCanceledException up to the caller
                if (cancellationToken.HasValue)
                {
                    tokenRegistration = cancellationToken.Value.Register(state => ((TaskCompletionSource <bool>)state).TrySetCanceled(), tcs);
                }

                // Await the handle or the cancellation token
                return(await tcs.Task);
            }
            finally
            {
                // Clean up registered wait handle
                registeredWaitHandle?.Unregister(null);

                // Dispose of the token we had to create to register for the cancellation token callback
                tokenRegistration?.Dispose();
            }
        }
        public async Task DisposeAsync()
        {
            var client = Interlocked.Exchange(ref this._client, null);

            if (client == null)
            {
                return;
            }
            _d?.Dispose();
            _d = null;
            try
            {
                await _lck.Release().ConfigureAwait(false);

                await _lck.Destroy().ConfigureAwait(false);
            }
            catch { }
        }
Exemple #17
0
            public void DisableCancellation()
            {
                if (_cancellationRegistration == null)
                {
                    return;
                }

                lock (_cancellationSync)
                {
                    if (_cancellationRegistration == null)
                    {
                        return;
                    }

                    _cancellationRegistration?.Dispose();
                    _cancellationRegistration = null;
                }
            }
Exemple #18
0
        // .NET Framework 4.0 an earlier do not have Task.Delay defined

        public static global::System.Threading.Tasks.Task Delay(int millisecondsDelay, CancellationToken cancellationToken)
        {
            TaskCompletionSource <bool> taskCompletionSource = new TaskCompletionSource <bool>();
            Timer timer = null;
            CancellationTokenRegistration?cancellationTokenRegistration = null;

            timer = new Timer(state => {
                taskCompletionSource.TrySetResult(true);

                timer.Dispose();
            }, null, millisecondsDelay, Timeout.Infinite);

            cancellationTokenRegistration = cancellationToken.Register(() => {
                timer.Change(0, Timeout.Infinite);

                cancellationTokenRegistration?.Dispose();
            });

            return(taskCompletionSource.Task);
        }
        public static async Task Timeout(this Task task, TimeSpan timeout, CancellationToken?cts = null)
        {
            CancellationTokenRegistration?ctr = null;
            TaskCompletionSource <bool>   tcs = new TaskCompletionSource <bool>();

            if (cts.HasValue)
            {
                ctr = cts.Value.Register(() =>
                {
                    tcs.TrySetCanceled();
                    ctr?.Dispose();
                });
            }

            if (timeout == TimeSpan.MaxValue)
            {
                await task;
                return;
            }

            var delay = Task.Delay(timeout).ContinueWith(d => throw new TimeoutException());
            await await Task.WhenAny(task, delay);
        }
 public bool CloseChrome()
 {
     if (IsOpenChrome)
     {
         if (process?.HasExited == false)
         {
             process?.Kill();
         }
         process?.Dispose();
         process = null;
         chromeDriver?.Quit();
         chromeDriver = null;
         service?.Dispose();
         service = null;
         cancellationTokenRegistration?.Dispose();
         cancellationTokenRegistration = null;
         tokenSource?.Dispose();
         tokenSource = null;
         StateChange?.Invoke(IsOpenChrome);
         return(true);
     }
     return(false);
 }
Exemple #21
0
        private static Task <CommandResult> Run(this string command, string workingDirectory,
                                                CancellationToken cancellationToken, IProcessOutputClassifier outputClassifier, TimeSpan?timeout = null)
        {
            TimeSpan timeOutSpan = timeout ?? TimeSpan.FromMinutes(120);

            Process process = CreateProcess(command, workingDirectory);

            var standardOutput        = new List <string>();
            var standardError         = new List <string>();
            var standardInfos         = new List <string>();
            var standardOutputResults = new TaskCompletionSource <List <string> >();
            var standardErrorResults  = new TaskCompletionSource <List <string> >();

            process.OutputDataReceived += (sender, e) => OnOutput(e, standardOutput, standardOutputResults);
            process.ErrorDataReceived  += (sender, e) => OnError(outputClassifier, e, standardError, standardInfos, standardErrorResults);

            var tcs = new TaskCompletionSource <CommandResult>();

            CancellationTokenRegistration registration = default;

            void OnDispose()
            {
                process.Exited -= OnProcessExit;
                registration.Dispose();
            }

            var stopwatch = new Stopwatch();

            async void OnProcessExit(object sender, EventArgs args)
            {
                stopwatch.Stop();
                var stdout = await standardOutputResults.Task;
                var stderr = await standardErrorResults.Task;

                var result = new CommandResult
                {
                    Command             = command,
                    ExitCode            = process.ExitCode,
                    IsSuccess           = standardError.Count == 0,
                    Output              = string.Join(Environment.NewLine, stdout),
                    Errors              = string.Join(Environment.NewLine, stderr),
                    Infos               = standardInfos,
                    ElapsedMilliseconds = stopwatch.ElapsedMilliseconds
                };

                tcs.TrySetResult(result);
                OnDispose();
            }

            process.Exited += OnProcessExit;

            registration = cancellationToken.Register(() =>
            {
                tcs.TrySetCanceled();
                KillProcessAndChilds(process);
                OnDispose();
            });

            try
            {
                stopwatch.Start();
                if (!process.Start())
                {
                    tcs.TrySetException(new InvalidOperationException("Failed to start process"));
                    OnDispose();
                }
                else
                {
                    Task.Run(() =>
                    {
                        if (!process.WaitForExit((int)Math.Min(timeOutSpan.TotalMilliseconds, int.MaxValue)))
                        {
                            tcs.TrySetException(new InvalidOperationException("Process timedout"));
                            OnDispose();
                        }
                    });
                }
            }
            catch (Exception e)
            {
                tcs.TrySetException(e);
                OnDispose();
            }
            process.BeginOutputReadLine();
            process.BeginErrorReadLine();
            return(tcs.Task);
        }
Exemple #22
0
        // StepsRunner should never throw exception to caller
        public async Task RunAsync(IExecutionContext jobContext, IList <IStep> steps)
        {
            ArgUtil.NotNull(jobContext, nameof(jobContext));
            ArgUtil.NotNull(steps, nameof(steps));

            // TaskResult:
            //  Abandoned (Server set this.)
            //  Canceled
            //  Failed
            //  Skipped
            //  Succeeded
            //  SucceededWithIssues
            CancellationTokenRegistration?jobCancelRegister = null;
            int stepIndex = 0;

            jobContext.Variables.Agent_JobStatus = jobContext.Result ?? TaskResult.Succeeded;
            foreach (IStep step in steps)
            {
                Trace.Info($"Processing step: DisplayName='{step.DisplayName}', ContinueOnError={step.ContinueOnError}, Enabled={step.Enabled}");
                ArgUtil.Equal(true, step.Enabled, nameof(step.Enabled));
                ArgUtil.NotNull(step.ExecutionContext, nameof(step.ExecutionContext));
                ArgUtil.NotNull(step.ExecutionContext.Variables, nameof(step.ExecutionContext.Variables));
                stepIndex++;

                // Start.
                step.ExecutionContext.Start();
                var taskStep = step as ITaskRunner;
                if (taskStep != null)
                {
                    HostContext.WritePerfCounter($"TaskStart_{taskStep.Task.Reference.Name}_{stepIndex}");
                }

                // Variable expansion.
                List <string> expansionWarnings;
                step.ExecutionContext.Variables.RecalculateExpanded(out expansionWarnings);
                expansionWarnings?.ForEach(x => step.ExecutionContext.Warning(x));

                var expressionManager = HostContext.GetService <IExpressionManager>();
                try
                {
                    // Register job cancellation call back only if job cancellation token not been fire before each step run
                    if (!jobContext.CancellationToken.IsCancellationRequested)
                    {
                        // Test the condition again. The job was canceled after the condition was originally evaluated.
                        jobCancelRegister = jobContext.CancellationToken.Register(() =>
                        {
                            // mark job as cancelled
                            jobContext.Result = TaskResult.Canceled;
                            jobContext.Variables.Agent_JobStatus = jobContext.Result;

                            step.ExecutionContext.Debug($"Re-evaluate condition on job cancellation for step: '{step.DisplayName}'.");
                            ConditionResult conditionReTestResult;
                            if (HostContext.AgentShutdownToken.IsCancellationRequested)
                            {
                                step.ExecutionContext.Debug($"Skip Re-evaluate condition on agent shutdown.");
                                conditionReTestResult = false;
                            }
                            else
                            {
                                try
                                {
                                    conditionReTestResult = expressionManager.Evaluate(step.ExecutionContext, step.Condition, hostTracingOnly: true);
                                }
                                catch (Exception ex)
                                {
                                    // Cancel the step since we get exception while re-evaluate step condition.
                                    Trace.Info("Caught exception from expression when re-test condition on job cancellation.");
                                    step.ExecutionContext.Error(ex);
                                    conditionReTestResult = false;
                                }
                            }

                            if (!conditionReTestResult.Value)
                            {
                                // Cancel the step.
                                Trace.Info("Cancel current running step.");
                                step.ExecutionContext.CancelToken();
                            }
                        });
                    }
                    else
                    {
                        if (jobContext.Result != TaskResult.Canceled)
                        {
                            // mark job as cancelled
                            jobContext.Result = TaskResult.Canceled;
                            jobContext.Variables.Agent_JobStatus = jobContext.Result;
                        }
                    }

                    // Evaluate condition.
                    step.ExecutionContext.Debug($"Evaluating condition for step: '{step.DisplayName}'");
                    Exception       conditionEvaluateError = null;
                    ConditionResult conditionResult;
                    if (HostContext.AgentShutdownToken.IsCancellationRequested)
                    {
                        step.ExecutionContext.Debug($"Skip evaluate condition on agent shutdown.");
                        conditionResult = false;
                    }
                    else
                    {
                        try
                        {
                            conditionResult = expressionManager.Evaluate(step.ExecutionContext, step.Condition);
                        }
                        catch (Exception ex)
                        {
                            Trace.Info("Caught exception from expression.");
                            Trace.Error(ex);
                            conditionResult        = false;
                            conditionEvaluateError = ex;
                        }
                    }

                    // no evaluate error but condition is false
                    if (!conditionResult.Value && conditionEvaluateError == null)
                    {
                        // Condition == false
                        Trace.Info("Skipping step due to condition evaluation.");
                        step.ExecutionContext.Complete(TaskResult.Skipped, resultCode: conditionResult.Trace);
                        continue;
                    }

                    if (conditionEvaluateError != null)
                    {
                        // fail the step since there is an evaluate error.
                        step.ExecutionContext.Error(conditionEvaluateError);
                        step.ExecutionContext.Complete(TaskResult.Failed);
                    }
                    else
                    {
                        // Run the step.
                        await RunStepAsync(step, jobContext.CancellationToken);
                    }
                }
                finally
                {
                    if (jobCancelRegister != null)
                    {
                        jobCancelRegister?.Dispose();
                        jobCancelRegister = null;
                    }
                }

                // Update the job result.
                if (step.ExecutionContext.Result == TaskResult.SucceededWithIssues ||
                    step.ExecutionContext.Result == TaskResult.Failed)
                {
                    Trace.Info($"Update job result with current step result '{step.ExecutionContext.Result}'.");
                    jobContext.Result = TaskResultUtil.MergeTaskResults(jobContext.Result, step.ExecutionContext.Result.Value);
                    jobContext.Variables.Agent_JobStatus = jobContext.Result;
                }
                else
                {
                    Trace.Info($"No need for updating job result with current step result '{step.ExecutionContext.Result}'.");
                }

                if (taskStep != null)
                {
                    HostContext.WritePerfCounter($"TaskCompleted_{taskStep.Task.Reference.Name}_{stepIndex}");
                }

                Trace.Info($"Current state: job state = '{jobContext.Result}'");
            }
        }
Exemple #23
0
 public override void PostStop()
 {
     _registration?.Dispose();
     base.PostStop();
 }
 public void Dispose()
 {
     _cancellationTokenRegistration.Dispose();
     _timeoutCancellationTokenSource.Dispose();
 }
        /// <summary>
        /// Receive a single frame from <paramref name="socket"/>, asynchronously, and decode as a string using <paramref name="encoding"/>.
        /// </summary>
        /// <param name="socket">The socket to receive from.</param>
        /// <param name="encoding">The encoding used to convert the frame's data to a string.</param>
        /// <param name="cancellationToken">The token used to propagate notification that this operation should be canceled.</param>
        /// <returns>The content of the received message frame as a string and boolean indicate if another frame of the same message follows..</returns>
        public static Task <(string, bool)> ReceiveFrameStringAsync(
            this NetMQSocket socket,
            Encoding encoding,
            CancellationToken cancellationToken = default(CancellationToken))
        {
            if (NetMQRuntime.Current == null)
            {
                throw new InvalidOperationException("NetMQRuntime must be created before calling async functions");
            }

            socket.AttachToRuntime();

            var msg = new Msg();

            msg.InitEmpty();

            if (socket.TryReceive(ref msg, TimeSpan.Zero))
            {
                var str = msg.Size > 0
                    ? msg.GetString(encoding)
                    : string.Empty;

                msg.Close();
                return(Task.FromResult((str, msg.HasMore)));
            }

            TaskCompletionSource <(string, bool)> source = new TaskCompletionSource <(string, bool)>();

            CancellationTokenRegistration?registration = null;

            if (cancellationToken.CanBeCanceled)
            {
                registration = cancellationToken.Register(PropagateCancel);
            }

            void Listener(object sender, NetMQSocketEventArgs args)
            {
                if (socket.TryReceive(ref msg, TimeSpan.Zero))
                {
                    var str = msg.Size > 0
                        ? msg.GetString(encoding)
                        : string.Empty;
                    bool more = msg.HasMore;
                    msg.Close();

                    socket.ReceiveReady -= Listener;
                    registration?.Dispose();
                    source.TrySetResult((str, more));
                }
            }

            void PropagateCancel()
            {
                socket.ReceiveReady -= Listener;
                registration?.Dispose();
                source.TrySetCanceled();
            }

            socket.ReceiveReady += Listener;

            return(source.Task);
        }
Exemple #26
0
        // StepsRunner should never throw exception to caller
        public async Task RunAsync(IExecutionContext jobContext)
        {
            ArgUtil.NotNull(jobContext, nameof(jobContext));
            ArgUtil.NotNull(jobContext.JobSteps, nameof(jobContext.JobSteps));

            // TaskResult:
            //  Abandoned (Server set this.)
            //  Canceled
            //  Failed
            //  Skipped
            //  Succeeded
            CancellationTokenRegistration?jobCancelRegister = null;

            jobContext.JobContext.Status = (jobContext.Result ?? TaskResult.Succeeded).ToActionResult();
            var  scopeInputs         = new Dictionary <string, PipelineContextData>(StringComparer.OrdinalIgnoreCase);
            bool checkPostJobActions = false;

            while (jobContext.JobSteps.Count > 0 || !checkPostJobActions)
            {
                if (jobContext.JobSteps.Count == 0 && !checkPostJobActions)
                {
                    checkPostJobActions = true;
                    while (jobContext.PostJobSteps.TryPop(out var postStep))
                    {
                        jobContext.JobSteps.Add(postStep);
                    }

                    continue;
                }

                var step = jobContext.JobSteps[0];
                jobContext.JobSteps.RemoveAt(0);

                Trace.Info($"Processing step: DisplayName='{step.DisplayName}'");
                ArgUtil.NotNull(step.ExecutionContext, nameof(step.ExecutionContext));
                ArgUtil.NotNull(step.ExecutionContext.Variables, nameof(step.ExecutionContext.Variables));

                // Start
                step.ExecutionContext.Start();

                // Expression functions
                step.ExecutionContext.ExpressionFunctions.Add(new FunctionInfo <AlwaysFunction>(PipelineTemplateConstants.Always, 0, 0));
                step.ExecutionContext.ExpressionFunctions.Add(new FunctionInfo <CancelledFunction>(PipelineTemplateConstants.Cancelled, 0, 0));
                step.ExecutionContext.ExpressionFunctions.Add(new FunctionInfo <FailureFunction>(PipelineTemplateConstants.Failure, 0, 0));
                step.ExecutionContext.ExpressionFunctions.Add(new FunctionInfo <SuccessFunction>(PipelineTemplateConstants.Success, 0, 0));
                step.ExecutionContext.ExpressionFunctions.Add(new FunctionInfo <HashFilesFunction>(PipelineTemplateConstants.HashFiles, 1, byte.MaxValue));

                step.ExecutionContext.ExpressionValues["steps"] = step.ExecutionContext.StepsContext.GetScope(step.ExecutionContext.ScopeName);

                // Populate env context for each step
                Trace.Info("Initialize Env context for step");
#if OS_WINDOWS
                var envContext = new DictionaryContextData();
#else
                var envContext = new CaseSensitiveDictionaryContextData();
#endif

                // Global env
                foreach (var pair in step.ExecutionContext.EnvironmentVariables)
                {
                    envContext[pair.Key] = new StringContextData(pair.Value ?? string.Empty);
                }

                // Stomps over with outside step env
                if (step.ExecutionContext.ExpressionValues.TryGetValue("env", out var envContextData))
                {
#if OS_WINDOWS
                    var dict = envContextData as DictionaryContextData;
#else
                    var dict = envContextData as CaseSensitiveDictionaryContextData;
#endif
                    foreach (var pair in dict)
                    {
                        envContext[pair.Key] = pair.Value;
                    }
                }

                step.ExecutionContext.ExpressionValues["env"] = envContext;

                bool evaluateStepEnvFailed = false;
                if (step is IActionRunner actionStep)
                {
                    // Set GITHUB_ACTION
                    step.ExecutionContext.SetGitHubContext("action", actionStep.Action.Name);

                    try
                    {
                        // Evaluate and merge action's env block to env context
                        var templateEvaluator = step.ExecutionContext.ToPipelineTemplateEvaluator();
                        var actionEnvironment = templateEvaluator.EvaluateStepEnvironment(actionStep.Action.Environment, step.ExecutionContext.ExpressionValues, step.ExecutionContext.ExpressionFunctions, VarUtil.EnvironmentVariableKeyComparer);
                        foreach (var env in actionEnvironment)
                        {
                            envContext[env.Key] = new StringContextData(env.Value ?? string.Empty);
                        }
                    }
                    catch (Exception ex)
                    {
                        // fail the step since there is an evaluate error.
                        Trace.Info("Caught exception from expression for step.env");
                        evaluateStepEnvFailed = true;
                        step.ExecutionContext.Error(ex);
                        CompleteStep(step, TaskResult.Failed);
                    }
                }

                if (!evaluateStepEnvFailed)
                {
                    try
                    {
                        // Register job cancellation call back only if job cancellation token not been fire before each step run
                        if (!jobContext.CancellationToken.IsCancellationRequested)
                        {
                            // Test the condition again. The job was canceled after the condition was originally evaluated.
                            jobCancelRegister = jobContext.CancellationToken.Register(() =>
                            {
                                // mark job as cancelled
                                jobContext.Result            = TaskResult.Canceled;
                                jobContext.JobContext.Status = jobContext.Result?.ToActionResult();

                                step.ExecutionContext.Debug($"Re-evaluate condition on job cancellation for step: '{step.DisplayName}'.");
                                var conditionReTestTraceWriter = new ConditionTraceWriter(Trace, null); // host tracing only
                                var conditionReTestResult      = false;
                                if (HostContext.RunnerShutdownToken.IsCancellationRequested)
                                {
                                    step.ExecutionContext.Debug($"Skip Re-evaluate condition on runner shutdown.");
                                }
                                else
                                {
                                    try
                                    {
                                        var templateEvaluator = step.ExecutionContext.ToPipelineTemplateEvaluator(conditionReTestTraceWriter);
                                        var condition         = new BasicExpressionToken(null, null, null, step.Condition);
                                        conditionReTestResult = templateEvaluator.EvaluateStepIf(condition, step.ExecutionContext.ExpressionValues, step.ExecutionContext.ExpressionFunctions, step.ExecutionContext.ToExpressionState());
                                    }
                                    catch (Exception ex)
                                    {
                                        // Cancel the step since we get exception while re-evaluate step condition.
                                        Trace.Info("Caught exception from expression when re-test condition on job cancellation.");
                                        step.ExecutionContext.Error(ex);
                                    }
                                }

                                if (!conditionReTestResult)
                                {
                                    // Cancel the step.
                                    Trace.Info("Cancel current running step.");
                                    step.ExecutionContext.CancelToken();
                                }
                            });
                        }
                        else
                        {
                            if (jobContext.Result != TaskResult.Canceled)
                            {
                                // mark job as cancelled
                                jobContext.Result            = TaskResult.Canceled;
                                jobContext.JobContext.Status = jobContext.Result?.ToActionResult();
                            }
                        }

                        // Evaluate condition.
                        step.ExecutionContext.Debug($"Evaluating condition for step: '{step.DisplayName}'");
                        var conditionTraceWriter   = new ConditionTraceWriter(Trace, step.ExecutionContext);
                        var conditionResult        = false;
                        var conditionEvaluateError = default(Exception);
                        if (HostContext.RunnerShutdownToken.IsCancellationRequested)
                        {
                            step.ExecutionContext.Debug($"Skip evaluate condition on runner shutdown.");
                        }
                        else
                        {
                            try
                            {
                                var templateEvaluator = step.ExecutionContext.ToPipelineTemplateEvaluator(conditionTraceWriter);
                                var condition         = new BasicExpressionToken(null, null, null, step.Condition);
                                conditionResult = templateEvaluator.EvaluateStepIf(condition, step.ExecutionContext.ExpressionValues, step.ExecutionContext.ExpressionFunctions, step.ExecutionContext.ToExpressionState());
                            }
                            catch (Exception ex)
                            {
                                Trace.Info("Caught exception from expression.");
                                Trace.Error(ex);
                                conditionEvaluateError = ex;
                            }
                        }

                        // no evaluate error but condition is false
                        if (!conditionResult && conditionEvaluateError == null)
                        {
                            // Condition == false
                            Trace.Info("Skipping step due to condition evaluation.");
                            CompleteStep(step, TaskResult.Skipped, resultCode: conditionTraceWriter.Trace);
                        }
                        else if (conditionEvaluateError != null)
                        {
                            // fail the step since there is an evaluate error.
                            step.ExecutionContext.Error(conditionEvaluateError);
                            CompleteStep(step, TaskResult.Failed);
                        }
                        else
                        {
                            // Run the step.
                            await RunStepAsync(step, jobContext.CancellationToken);

                            CompleteStep(step);
                        }
                    }
                    finally
                    {
                        if (jobCancelRegister != null)
                        {
                            jobCancelRegister?.Dispose();
                            jobCancelRegister = null;
                        }
                    }
                }

                // Update the job result.
                if (step.ExecutionContext.Result == TaskResult.Failed)
                {
                    Trace.Info($"Update job result with current step result '{step.ExecutionContext.Result}'.");
                    jobContext.Result            = TaskResultUtil.MergeTaskResults(jobContext.Result, step.ExecutionContext.Result.Value);
                    jobContext.JobContext.Status = jobContext.Result?.ToActionResult();
                }
                else
                {
                    Trace.Info($"No need for updating job result with current step result '{step.ExecutionContext.Result}'.");
                }

                Trace.Info($"Current state: job state = '{jobContext.Result}'");
            }
        }
 public Task StopAsync(CancellationToken cancellationToken)
 {
     _stopped.Cancel();
     _stoppedRegistration?.Dispose();
     return(Task.CompletedTask);
 }
Exemple #28
0
        public Task SendMailAsync(MailMessage message, CancellationToken cancellationToken)
        {
            if (cancellationToken.IsCancellationRequested)
            {
                return(Task.FromCanceled(cancellationToken));
            }

            // Create a TaskCompletionSource to represent the operation
            var tcs = new TaskCompletionSource();

            CancellationTokenRegistration ctr = default;

            // Indicates whether the CTR has been set - captured in handler
            int state = 0;

            // Register a handler that will transfer completion results to the TCS Task
            SendCompletedEventHandler?handler = null;

            handler = (sender, e) =>
            {
                if (e.UserState == tcs)
                {
                    try
                    {
                        ((SmtpClient)sender).SendCompleted -= handler;
                        if (Interlocked.Exchange(ref state, 1) != 0)
                        {
                            // A CTR has been set, we have to wait until it completes before completing the task
                            ctr.Dispose();
                        }
                    }
                    catch (ObjectDisposedException) { } // SendAsyncCancel will throw if SmtpClient was disposed
                    finally
                    {
                        if (e.Error != null)
                        {
                            tcs.TrySetException(e.Error);
                        }
                        else if (e.Cancelled)
                        {
                            tcs.TrySetCanceled();
                        }
                        else
                        {
                            tcs.TrySetResult();
                        }
                    }
                }
            };
            SendCompleted += handler;

            // Start the async operation.
            try
            {
                SendAsync(message, tcs);
            }
            catch
            {
                SendCompleted -= handler;
                throw;
            }

            ctr = cancellationToken.Register(s =>
            {
                ((SmtpClient)s !).SendAsyncCancel();
            }, this);

            if (Interlocked.Exchange(ref state, 1) != 0)
            {
                // SendCompleted was already invoked, ensure the CTR completes before returning the task
                ctr.Dispose();
            }

            // Return the task to represent the asynchronous operation
            return(tcs.Task);
        }
 protected override void Dispose() => _registration.Dispose();
Exemple #30
0
        /// <summary>
        /// Registers a continuation for the task that will run when the task is complete.
        /// </summary>
        /// <typeparam name="T">The type returned by the continuation.</typeparam>
        /// <param name="p_continuation">The continuation to run after the task completes.
        /// The function takes the completed task as an argument and can return a value.</param>
        /// <param name="p_cancellationToken">The cancellation token.</param>
        /// <returns>A new Task that returns the value returned by the continuation after both
        /// the task and the continuation are complete.</returns>
        public UnityTask <UnityTask> ContinueWith(Func <UnityTask, UnityTask> p_continuation, System.Threading.Tasks.CancellationToken p_cancellationToken)
        {
            bool completed = false;

            UnityTaskCompletionSource <UnityTask> utcs        = new UnityTaskCompletionSource <UnityTask>();
            CancellationTokenRegistration         cancelToken = p_cancellationToken.Register(() => utcs.TrySetCanceled());

            // 此处防止判断为false之后正好执行完毕
            completed = IsCompleted;
            if (!completed)
            {
                m_continuationActions.Add(t =>
                {
                    //if (t.IsFaulted)
                    //{
                    //    utcs.TrySetException(t.Exception);
                    //    cancelToken.Dispose();
                    //}
                    //else
                    //{
                    try
                    {
                        UnityTask result = p_continuation(t);
                        utcs.TrySetResult(result);
                        cancelToken.Dispose();
                    }
                    catch (Exception ex)
                    {
                        utcs.TrySetException(ex);
                        cancelToken.Dispose();
                    }
                    //}
                });
            }
            else
            {
                ForegroundInvoker.Invoke(() =>
                {
                    //if (this.IsFaulted)
                    //{
                    //    utcs.TrySetException(this.Exception);
                    //    cancelToken.Dispose();
                    //}
                    //else
                    //{
                    try
                    {
                        UnityTask result = p_continuation(this);
                        utcs.TrySetResult(result);
                        cancelToken.Dispose();
                    }
                    catch (Exception ex)
                    {
                        utcs.TrySetException(ex);
                        cancelToken.Dispose();
                    }
                    //}
                });
            }

            return(utcs.Task);
        }