internal void BatchCompileDirectory(Object unused) { _thread = Thread.CurrentThread; try { using (new HttpContextWrapper(_context)) { // Set some thread data to remember that this is a batch compilation thread CallContext.SetData(CallContextBatchCompilerSlotName, this); // Do the impersonation _context.Impersonation.Start(true /*forGlobalCode*/, false /*throwOnError*/); Debug.Trace("PreservedAssemblyEntry", "Starting batch compilation of directory " + _baseVirtualDir); try { CodeDomBatchManager.BatchCompile(_baseVirtualDir, _context); } // eat exceptions and fail batch compilation silently #if DBG catch (Exception e) { if (e is ThreadAbortException) { Debug.Trace("PreservedAssemblyEntry", "Batch compilation of directory " + _baseVirtualDir + " was aborted."); } else { Debug.Trace("PreservedAssemblyEntry", "Batch compilation of directory " + _baseVirtualDir + " failed."); } Util.DumpExceptionStack(e); return; } #else catch (Exception) { return; } #endif finally { _context.Impersonation.Stop(); CallContext.SetData(CallContextBatchCompilerSlotName, null); if (WasAddedToBackgroundThreadsList) { PreservedAssemblyEntry.RemoveBackgroundBatchCompilation(this); } } } // Batching was performed successfully Debug.Trace("PreservedAssemblyEntry", "Batch compilation of directory " + _baseVirtualDir + " was successful."); _success = true; } catch (ThreadAbortException) { // to consume thread abort exception (so that the thread pool doesn't know) Thread.ResetAbort(); } catch { throw; } // Prevent Exception Filter Security Issue (ASURT 122826) finally { _thread = null; _event.Set(); } }
/* * Try batching the directory if not done yet. */ private static bool BatchCompileDirectory(HttpContext context, string baseVirtualDir) { // Don't do it if batching is disabled if (!CompilationConfiguration.IsBatchingEnabled(context)) { return(false); } if (AlreadyBatched(baseVirtualDir)) { return(false); } Debug.Trace("PreservedAssemblyEntry", "Need to batch compile " + baseVirtualDir); // If we're already in a batch compilation tread, no need to start another one if (BackgroundBatchCompiler.IsBatchCompilationThread()) { Debug.Trace("PreservedAssemblyEntry", "Already in batch compilation thread. No need to start a new one."); CodeDomBatchManager.BatchCompile(baseVirtualDir, context); return(true); } // Notify HttpRuntime so that it might need to abort compilation on shutdown HttpRuntime.NotifyThatSomeBatchCompilationStarted(); ManualResetEvent batchEvent = new ManualResetEvent(false); // Pass it a Clone of the context, since it's not thread safe. Mostly, this is important // for the ConfigPath (ASURT 82744) BackgroundBatchCompiler bbc = new BackgroundBatchCompiler(context.Clone(), baseVirtualDir, batchEvent); // Start the batch processing try { ThreadPool.QueueUserWorkItem(bbc.BatchCallback); } catch { return(false); } // Register for BeforeDoneWithSession event context.BeforeDoneWithSession += new EventHandler(bbc.BeforeDoneWithSessionHandler); // Wait a certain time for it to complete int timeout = 1000 * CompilationConfiguration.GetBatchTimeout(context); Debug.Trace("PreservedAssemblyEntry", "Waiting for " + timeout + " ms"); if (batchEvent.WaitOne(timeout, false)) { Debug.Trace("PreservedAssemblyEntry", "The background thread is done for " + baseVirtualDir + " (Success=" + bbc.Success + ")"); return(bbc.Success); } // It didn't have time to complete. Let it run in the background. Debug.Trace("PreservedAssemblyEntry", "The background thread is still going for " + baseVirtualDir); // Add it to the list of background compilations, in case it needs to be aborted AddBackgroundBatchCompilation(bbc); bbc.WasAddedToBackgroundThreadsList = true; return(false); }