Esempio n. 1
0
        internal void SubmitSnippet(SnippetInfo snippetInfo, TaskCompletionSource <SnippetResult> completion)
        {
            // check if we need to re-introduce some domains in the pool
            if (Interlocked.Read(ref numberOfThreadsInPool) < NumberOfDomainsInPool)
            {
                // A sort of "double-check optimization": we enter here only if there is a shortage of threads/domains, but
                // we actually create one only if there is a slot
                int emptySlotIdx = -1;
                lock (poolLock) {
                    // find the empty slot
                    for (int i = 0; i < NumberOfDomainsInPool; ++i)
                    {
                        if (poolDomains[i] == null)
                        {
                            poolDomains[i] = new PooledDomainData();
                            emptySlotIdx   = i;
                        }
                    }
                }

                if (emptySlotIdx >= 0)
                {
                    var thread = CreateDomainThread(emptySlotIdx);
                    thread.Start();
                }
            }

            // Store the continuation _before_ adding the snippet info the the processing queue
            if (!String.IsNullOrEmpty(snippetInfo.submissionId) && completion != null)
            {
                submissionMap[snippetInfo.submissionId] = completion;
            }
            snippetsQueue.Add(snippetInfo);
        }
Esempio n. 2
0
        private void InitializeDomainPool()
        {
            watchdogThread = new Thread(WatchdogThreadFunc);

            for (int i = 0; i < NumberOfDomainsInPool; ++i)
            {
                poolDomains[i] = new PooledDomainData();
                var thread = CreateDomainThread(i);
                thread.Start();
            }

            watchdogThread.Priority = ThreadPriority.AboveNormal;
            watchdogThread.Start();
        }
Esempio n. 3
0
 internal void ResetContextFor(PooledDomainData domainData)
 {
     domainData.isAborting = 0;
     hostContext.ResetCountersForAppDomain(domainData.domainId);
 }
Esempio n. 4
0
        private void WatchdogThreadFunc()
        {
            while (!isExiting)
            {
                // This is a watchdog; it does not need to be precise.
                // It can be improved by recomputing the next check time (i.e. when a snippet expires)
                // at each submission, but for now we are good.

                // We sleep for a while, than check
                try {
                    //Thread.Sleep(1000);
                    HostEvent hostEvent;
                    if (defaultDomainManager.GetHostMessage(1000, out hostEvent))
                    {
                        System.Diagnostics.Debug.WriteLine("Watchdog: message from host for AppDomain " + hostEvent.appDomainId);
                        // Process event
                        switch ((HostEventType)hostEvent.eventType)
                        {
                        case HostEventType.OutOfTasks: {
                            PooledDomainData poolDomain = FindByAppDomainId(hostEvent.appDomainId);
                            if (poolDomain != null)
                            {
                                if (Interlocked.CompareExchange(ref poolDomain.isAborting, 1, 0) == 0)
                                {
                                    poolDomain.mainThread.Abort(threadsExaustedAbortToken);
                                }
                            }
                        }
                        break;
                        }
                    }
                    else
                    {
                        long currentTime = StopwatchExtensions.GetTimestampMillis();
                        //System.Diagnostics.Debug.WriteLine("Watchdog: check at " + currentTime);

                        for (int i = 0; i < NumberOfDomainsInPool; ++i)
                        {
                            // Something is running?
                            PooledDomainData poolDomain = null;
                            lock (poolLock) {
                                poolDomain = poolDomains[i];
                            }

                            if (poolDomain != null)
                            {
                                long snippetStartTime = Thread.VolatileRead(ref poolDomain.timeOfSubmission);
                                if (snippetStartTime > 0)
                                {
                                    // For too long?
                                    long millisRunning = currentTime - snippetStartTime;
                                    if (millisRunning > runningThreshold)
                                    {
                                        // Abort Thread i / Unload domain i
                                        // Calling abort here is fine: the host will escalate it for us if it times
                                        // out. Otherwise, we can still catch it and reuse the AppDomain
                                        System.Diagnostics.Debug.WriteLine("Timeout: aborting thread #{0} in domain {1} ({2} ms)", i, poolDomains[i].domainId, millisRunning);

                                        // Avoid to call Abort twice
                                        Thread.VolatileWrite(ref poolDomains[i].timeOfSubmission, 0);
                                        poolDomains[i].mainThread.Abort(timeoutAbortToken);
                                    }
                                    // Check also for appDomain.MonitoringTotalProcessorTime
                                    //else if (poolDomains[i].appDomain.MonitoringTotalProcessorTime > MaxCpuTime)
                                    //   //TODO
                                    //}
                                }

                                // If our thread was aborted rudely, we need to create a new one
                                if (poolDomain.mainThread == null || poolDomain.mainThread.ThreadState == System.Threading.ThreadState.Aborted)
                                {
                                    defaultDomainManager.HostUnloadDomain(poolDomain.domainId);
                                    poolDomains[i] = new PooledDomainData();
                                    var thread = CreateDomainThread(i);
                                    thread.Start();
                                }
                            }
                        }
                    }

                    // Ensure there is at least a thread in the pool
                    if (numberOfThreadsInPool < 1)
                    {
                        poolDomains[0] = new PooledDomainData();
                        var thread = CreateDomainThread(0);
                        thread.Start();
                    }
                }
                catch (ThreadInterruptedException) {
                    // Do we need to exit? Simply cycle back to check exit status
                }
            }
        }